Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ fe9f1a6d

History | View | Annotate | Download (39.8 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 void
62
pm_format(struct f_path_mask *p, buffer *buf)
63
{
64
  buffer_puts(buf, "[= ");
65

    
66
  while (p)
67
  {
68
    switch(p->kind)
69
    {
70
    case PM_ASN:
71
      buffer_print(buf, "%u ", p->val);
72
      break;
73

    
74
    case PM_QUESTION:
75
      buffer_puts(buf, "? ");
76
      break;
77

    
78
    case PM_ASTERISK:
79
      buffer_puts(buf, "* ");
80
      break;
81

    
82
    case PM_ASN_EXPR:
83
      buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
84
      break;
85
    }
86

    
87
    p = p->next;
88
  }
89

    
90
  buffer_puts(buf, "=]");
91
}
92

    
93
static inline int
94
uint_cmp(uint i1, uint i2)
95
{
96
  return (int)(i1 > i2) - (int)(i1 < i2);
97
}
98

    
99
static inline int
100
u64_cmp(u64 i1, u64 i2)
101
{
102
  return (int)(i1 > i2) - (int)(i1 < i2);
103
}
104

    
105
/**
106
 * val_compare - compare two values
107
 * @v1: first value
108
 * @v2: second value
109
 *
110
 * Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
111
 * error. Tree module relies on this giving consistent results so
112
 * that it can be used for building balanced trees.
113
 */
114
int
115
val_compare(struct f_val v1, struct f_val v2)
116
{
117
  int rc;
118

    
119
  if (v1.type != v2.type) {
120
    if (v1.type == T_VOID)        /* Hack for else */
121
      return -1;
122
    if (v2.type == T_VOID)
123
      return 1;
124

    
125
#ifndef IPV6
126
    /* IP->Quad implicit conversion */
127
    if ((v1.type == T_QUAD) && (v2.type == T_IP))
128
      return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
129
    if ((v1.type == T_IP) && (v2.type == T_QUAD))
130
      return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
131
#endif
132

    
133
    debug( "Types do not match in val_compare\n" );
134
    return CMP_ERROR;
135
  }
136

    
137
  switch (v1.type) {
138
  case T_VOID:
139
    return 0;
140
  case T_ENUM:
141
  case T_INT:
142
  case T_BOOL:
143
  case T_PAIR:
144
  case T_QUAD:
145
    return uint_cmp(v1.val.i, v2.val.i);
146
  case T_EC:
147
    return u64_cmp(v1.val.ec, v2.val.ec);
148
  case T_IP:
149
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
150
  case T_PREFIX:
151
    if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
152
      return rc;
153
    return uint_cmp(v1.val.px.len, v2.val.px.len);
154
  case T_STRING:
155
    return strcmp(v1.val.s, v2.val.s);
156
  default:
157
    return CMP_ERROR;
158
  }
159
}
160

    
161
static int
162
pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2)
163
{
164
  while (m1 && m2)
165
  {
166
    if ((m1->kind != m2->kind) || (m1->val != m2->val))
167
      return 0;
168

    
169
    m1 = m1->next;
170
    m2 = m2->next;
171
  }
172

    
173
 return !m1 && !m2;
174
}
175

    
176
/**
177
 * val_same - compare two values
178
 * @v1: first value
179
 * @v2: second value
180
 *
181
 * Compares two values and returns 1 if they are same and 0 if not.
182
 * Comparison of values of different types is valid and returns 0.
183
 */
184
int
185
val_same(struct f_val v1, struct f_val v2)
186
{
187
  int rc;
188

    
189
  rc = val_compare(v1, v2);
190
  if (rc != CMP_ERROR)
191
    return !rc;
192

    
193
  if (v1.type != v2.type)
194
    return 0;
195

    
196
  switch (v1.type) {
197
  case T_PATH_MASK:
198
    return pm_path_same(v1.val.path_mask, v2.val.path_mask);
199
  case T_PATH:
200
  case T_CLIST:
201
  case T_ECLIST:
202
    return adata_same(v1.val.ad, v2.val.ad);
203
  case T_SET:
204
    return same_tree(v1.val.t, v2.val.t);
205
  case T_PREFIX_SET:
206
    return trie_same(v1.val.ti, v2.val.ti);
207
  default:
208
    bug("Invalid type in val_same(): %x", v1.type);
209
  }
210
}
211

    
212
void
213
fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
214
{
215
  *l = *h = px->len & LEN_MASK;
216

    
217
  if (px->len & LEN_MINUS)
218
    *l = 0;
219

    
220
  else if (px->len & LEN_PLUS)
221
    *h = MAX_PREFIX_LENGTH;
222

    
223
  else if (px->len & LEN_RANGE)
224
    {
225
      *l = 0xff & (px->len >> 16);
226
      *h = 0xff & (px->len >> 8);
227
    }
228
}
229

    
230
static int
231
clist_set_type(struct f_tree *set, struct f_val *v)
232
{
233
 switch (set->from.type) {
234
  case T_PAIR:
235
    v->type = T_PAIR;
236
    return 1;
237
  case T_QUAD:
238
#ifndef IPV6
239
  case T_IP:
240
#endif
241
    v->type = T_QUAD;
242
    return 1;
243
    break;
244
  default:
245
    v->type = T_VOID;
246
    return 0;
247
  }
248
}
249

    
250
static inline int
251
eclist_set_type(struct f_tree *set)
252
{ return set->from.type == T_EC; }
253

    
254
static int
255
clist_match_set(struct adata *clist, struct f_tree *set)
256
{
257
  if (!clist)
258
    return 0;
259

    
260
  struct f_val v;
261
  if (!clist_set_type(set, &v))
262
    return CMP_ERROR;
263

    
264
  u32 *l = (u32 *) clist->data;
265
  u32 *end = l + clist->length/4;
266

    
267
  while (l < end) {
268
    v.val.i = *l++;
269
    if (find_tree(set, v))
270
      return 1;
271
  }
272
  return 0;
273
}
274

    
275
static int
276
eclist_match_set(struct adata *list, struct f_tree *set)
277
{
278
  if (!list)
279
    return 0;
280

    
281
  if (!eclist_set_type(set))
282
    return CMP_ERROR;
283

    
284
  struct f_val v;
285
  u32 *l = int_set_get_data(list);
286
  int len = int_set_get_size(list);
287
  int i;
288

    
289
  v.type = T_EC;
290
  for (i = 0; i < len; i += 2) {
291
    v.val.ec = ec_get(l, i);
292
    if (find_tree(set, v))
293
      return 1;
294
  }
295

    
296
  return 0;
297
}
298

    
299
static struct adata *
300
clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
301
{
302
  if (!list)
303
    return NULL;
304

    
305
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
306
  struct f_val v;
307
  if (tree)
308
    clist_set_type(set.val.t, &v);
309
  else
310
    v.type = T_PAIR;
311

    
312
  int len = int_set_get_size(list);
313
  u32 *l = int_set_get_data(list);
314
  u32 tmp[len];
315
  u32 *k = tmp;
316
  u32 *end = l + len;
317

    
318
  while (l < end) {
319
    v.val.i = *l++;
320
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
321
    if ((tree ? !!find_tree(set.val.t, v) : int_set_contains(set.val.ad, v.val.i)) == pos)
322
      *k++ = v.val.i;
323
  }
324

    
325
  int nl = (k - tmp) * 4;
326
  if (nl == list->length)
327
    return list;
328

    
329
  struct adata *res = adata_empty(pool, nl);
330
  memcpy(res->data, tmp, nl);
331
  return res;
332
}
333

    
334
static struct adata *
335
eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
336
{
337
  if (!list)
338
    return NULL;
339

    
340
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
341
  struct f_val v;
342

    
343
  int len = int_set_get_size(list);
344
  u32 *l = int_set_get_data(list);
345
  u32 tmp[len];
346
  u32 *k = tmp;
347
  int i;
348

    
349
  v.type = T_EC;
350
  for (i = 0; i < len; i += 2) {
351
    v.val.ec = ec_get(l, i);
352
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
353
    if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
354
      *k++ = l[i];
355
      *k++ = l[i+1];
356
    }
357
  }
358

    
359
  int nl = (k - tmp) * 4;
360
  if (nl == list->length)
361
    return list;
362

    
363
  struct adata *res = adata_empty(pool, nl);
364
  memcpy(res->data, tmp, nl);
365
  return res;
366
}
367

    
368
/**
369
 * val_in_range - implement |~| operator
370
 * @v1: element
371
 * @v2: set
372
 *
373
 * Checks if @v1 is element (|~| operator) of @v2.
374
 */
375
static int
376
val_in_range(struct f_val v1, struct f_val v2)
377
{
378
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
379
    return as_path_match(v1.val.ad, v2.val.path_mask);
380

    
381
  if ((v1.type == T_INT) && (v2.type == T_PATH))
382
    return as_path_contains(v2.val.ad, v1.val.i, 1);
383

    
384
  if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
385
    return int_set_contains(v2.val.ad, v1.val.i);
386
#ifndef IPV6
387
  /* IP->Quad implicit conversion */
388
  if ((v1.type == T_IP) && (v2.type == T_CLIST))
389
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
390
#endif
391

    
392
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
393
    return ec_set_contains(v2.val.ad, v1.val.ec);
394

    
395
  if ((v1.type == T_STRING) && (v2.type == T_STRING))
396
    return patmatch(v2.val.s, v1.val.s);
397

    
398
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
399
    return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
400

    
401
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
402
    return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
403

    
404
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
405
    return trie_match_fprefix(v2.val.ti, &v1.val.px);
406

    
407
  if (v2.type != T_SET)
408
    return CMP_ERROR;
409

    
410
  /* With integrated Quad<->IP implicit conversion */
411
  if ((v1.type == v2.val.t->from.type) ||
412
      ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
413
    return !!find_tree(v2.val.t, v1);
414

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

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

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

    
424
  return CMP_ERROR;
425
}
426

    
427
/*
428
 * val_format - format filter value
429
 */
430
void
431
val_format(struct f_val v, buffer *buf)
432
{
433
  char buf2[1024];
434
  switch (v.type)
435
  {
436
  case T_VOID:        buffer_puts(buf, "(void)"); return;
437
  case T_BOOL:        buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
438
  case T_INT:        buffer_print(buf, "%u", v.val.i); return;
439
  case T_STRING: buffer_print(buf, "%s", v.val.s); return;
440
  case T_IP:        buffer_print(buf, "%I", v.val.px.ip); return;
441
  case T_PREFIX: buffer_print(buf, "%I/%d", v.val.px.ip, v.val.px.len); return;
442
  case T_PAIR:        buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
443
  case T_QUAD:        buffer_print(buf, "%R", v.val.i); return;
444
  case T_EC:        ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
445
  case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
446
  case T_SET:        tree_format(v.val.t, buf); return;
447
  case T_ENUM:        buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return;
448
  case T_PATH:        as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
449
  case T_CLIST:        int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
450
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
451
  case T_PATH_MASK: pm_format(v.val.path_mask, buf); return;
452
  default:        buffer_print(buf, "[unknown type %x]", v.type); return;
453
  }
454
}
455

    
456
static struct rte **f_rte;
457
static struct rta *f_old_rta;
458
static struct ea_list **f_tmp_attrs;
459
static struct linpool *f_pool;
460
static struct buffer f_buf;
461
static int f_flags;
462

    
463
static inline void f_rte_cow(void)
464
{
465
  *f_rte = rte_cow(*f_rte);
466
}
467

    
468
/*
469
 * rta_cow - prepare rta for modification by filter
470
 */
471
static void
472
f_rta_cow(void)
473
{
474
  if (!rta_is_cached((*f_rte)->attrs))
475
    return;
476

    
477
  /* Prepare to modify rte */
478
  f_rte_cow();
479

    
480
  /* Store old rta to free it later, it stores reference from rte_cow() */
481
  f_old_rta = (*f_rte)->attrs;
482

    
483
  /*
484
   * Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
485
   * with f_old_rta (they will be copied when the cached rta will be obtained
486
   * at the end of f_run()), also the lock of hostentry is inherited (we
487
   * suppose hostentry is not changed by filters).
488
   */
489
  (*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
490
}
491

    
492
static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
493

    
494
#define runtime(x) do { \
495
    log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
496
    res.type = T_RETURN; \
497
    res.val.i = F_ERROR; \
498
    return res; \
499
  } while(0)
500

    
501
#define ARG(x,y) \
502
        x = interpret(what->y); \
503
        if (x.type & T_RETURN) \
504
                return x;
505

    
506
#define ONEARG ARG(v1, a1.p)
507
#define TWOARGS ARG(v1, a1.p) \
508
                ARG(v2, a2.p)
509
#define TWOARGS_C TWOARGS \
510
                  if (v1.type != v2.type) \
511
                    runtime( "Can't operate with values of incompatible types" );
512
#define ACCESS_RTE \
513
  do { if (!f_rte) runtime("No route to access"); } while (0)
514

    
515
#define BITFIELD_MASK(what) \
516
  (1u << (what->a2.i >> 24))
517

    
518
/**
519
 * interpret
520
 * @what: filter to interpret
521
 *
522
 * Interpret given tree of filter instructions. This is core function
523
 * of filter system and does all the hard work.
524
 *
525
 * Each instruction has 4 fields: code (which is instruction code),
526
 * aux (which is extension to instruction code, typically type),
527
 * arg1 and arg2 - arguments. Depending on instruction, arguments
528
 * are either integers, or pointers to instruction trees. Common
529
 * instructions like +, that have two expressions as arguments use
530
 * TWOARGS macro to get both of them evaluated.
531
 *
532
 * &f_val structures are copied around, so there are no problems with
533
 * memory managment.
534
 */
535
static struct f_val
536
interpret(struct f_inst *what)
537
{
538
  struct symbol *sym;
539
  struct f_val v1, v2, res, *vp;
540
  unsigned u1, u2;
541
  int i;
542
  u32 as;
543

    
544
  res.type = T_VOID;
545
  if (!what)
546
    return res;
547

    
548
  switch(what->code) {
549
  case ',':
550
    TWOARGS;
551
    break;
552

    
553
/* Binary operators */
554
  case '+':
555
    TWOARGS_C;
556
    switch (res.type = v1.type) {
557
    case T_VOID: runtime( "Can't operate with values of type void" );
558
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
559
    default: runtime( "Usage of unknown type" );
560
    }
561
    break;
562
  case '-':
563
    TWOARGS_C;
564
    switch (res.type = v1.type) {
565
    case T_VOID: runtime( "Can't operate with values of type void" );
566
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
567
    default: runtime( "Usage of unknown type" );
568
    }
569
    break;
570
  case '*':
571
    TWOARGS_C;
572
    switch (res.type = v1.type) {
573
    case T_VOID: runtime( "Can't operate with values of type void" );
574
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
575
    default: runtime( "Usage of unknown type" );
576
    }
577
    break;
578
  case '/':
579
    TWOARGS_C;
580
    switch (res.type = v1.type) {
581
    case T_VOID: runtime( "Can't operate with values of type void" );
582
    case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
583
                      res.val.i = v1.val.i / v2.val.i; break;
584
    default: runtime( "Usage of unknown type" );
585
    }
586
    break;
587

    
588
  case '&':
589
  case '|':
590
    ARG(v1, a1.p);
591
    if (v1.type != T_BOOL)
592
      runtime( "Can't do boolean operation on non-booleans" );
593
    if (v1.val.i == (what->code == '|')) {
594
      res.type = T_BOOL;
595
      res.val.i = v1.val.i;
596
      break;
597
    }
598

    
599
    ARG(v2, a2.p);
600
    if (v2.type != T_BOOL)
601
      runtime( "Can't do boolean operation on non-booleans" );
602
    res.type = T_BOOL;
603
    res.val.i = v2.val.i;
604
    break;
605

    
606
  case P('m','p'):
607
    TWOARGS;
608
    if ((v1.type != T_INT) || (v2.type != T_INT))
609
      runtime( "Can't operate with value of non-integer type in pair constructor" );
610
    u1 = v1.val.i;
611
    u2 = v2.val.i;
612
    if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
613
      runtime( "Can't operate with value out of bounds in pair constructor" );
614
    res.val.i = (u1 << 16) | u2;
615
    res.type = T_PAIR;
616
    break;
617

    
618
  case P('m','c'):
619
    {
620
      TWOARGS;
621

    
622
      int check, ipv4_used;
623
      u32 key, val;
624

    
625
      if (v1.type == T_INT) {
626
        ipv4_used = 0; key = v1.val.i;
627
      }
628
      else if (v1.type == T_QUAD) {
629
        ipv4_used = 1; key = v1.val.i;
630
      }
631
#ifndef IPV6
632
      /* IP->Quad implicit conversion */
633
      else if (v1.type == T_IP) {
634
        ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
635
      }
636
#endif
637
      else
638
        runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
639

    
640
      if (v2.type != T_INT)
641
        runtime("Can't operate with value of non-integer type in EC constructor");
642
      val = v2.val.i;
643

    
644
      res.type = T_EC;
645

    
646
      if (what->aux == EC_GENERIC) {
647
        check = 0; res.val.ec = ec_generic(key, val);
648
      }
649
      else if (ipv4_used) {
650
        check = 1; res.val.ec = ec_ip4(what->aux, key, val);
651
      }
652
      else if (key < 0x10000) {
653
        check = 0; res.val.ec = ec_as2(what->aux, key, val);
654
      }
655
      else {
656
        check = 1; res.val.ec = ec_as4(what->aux, key, val);
657
      }
658

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

    
662
      break;
663
    }
664

    
665
/* Relational operators */
666

    
667
#define COMPARE(x) \
668
    TWOARGS; \
669
    i = val_compare(v1, v2); \
670
    if (i==CMP_ERROR) \
671
      runtime( "Can't compare values of incompatible types" ); \
672
    res.type = T_BOOL; \
673
    res.val.i = (x); \
674
    break;
675

    
676
#define SAME(x) \
677
    TWOARGS; \
678
    i = val_same(v1, v2); \
679
    res.type = T_BOOL; \
680
    res.val.i = (x); \
681
    break;
682

    
683
  case P('!','='): SAME(!i);
684
  case P('=','='): SAME(i);
685
  case '<': COMPARE(i==-1);
686
  case P('<','='): COMPARE(i!=1);
687

    
688
  case '!':
689
    ONEARG;
690
    if (v1.type != T_BOOL)
691
      runtime( "Not applied to non-boolean" );
692
    res = v1;
693
    res.val.i = !res.val.i;
694
    break;
695

    
696
  case '~':
697
    TWOARGS;
698
    res.type = T_BOOL;
699
    res.val.i = val_in_range(v1, v2);
700
    if (res.val.i == CMP_ERROR)
701
      runtime( "~ applied on unknown type pair" );
702
    res.val.i = !!res.val.i;
703
    break;
704
  case P('d','e'):
705
    ONEARG;
706
    res.type = T_BOOL;
707
    res.val.i = (v1.type != T_VOID);
708
    break;
709

    
710
  /* Set to indirect value, a1 = variable, a2 = value */
711
  case 's':
712
    ARG(v2, a2.p);
713
    sym = what->a1.p;
714
    vp = sym->def;
715
    if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
716
#ifndef IPV6
717
      /* IP->Quad implicit conversion */
718
      if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
719
        vp->type = T_QUAD;
720
        vp->val.i = ipa_to_u32(v2.val.px.ip);
721
        break;
722
      }
723
#endif
724
      runtime( "Assigning to variable of incompatible type" );
725
    }
726
    *vp = v2;
727
    break;
728

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

    
733
    if (res.type == T_PREFIX_SET)
734
      res.val.ti = what->a2.p;
735
    else if (res.type == T_SET)
736
      res.val.t = what->a2.p;
737
    else if (res.type == T_STRING)
738
      res.val.s = what->a2.p;
739
    else
740
      res.val.i = what->a2.i;
741
    break;
742
  case 'V':
743
  case 'C':
744
    res = * ((struct f_val *) what->a1.p);
745
    break;
746
  case 'p':
747
    ONEARG;
748
    val_format(v1, &f_buf);
749
    break;
750
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
751
    ONEARG;
752
    if (v1.type != T_BOOL)
753
      runtime( "If requires boolean expression" );
754
    if (v1.val.i) {
755
      ARG(res,a2.p);
756
      res.val.i = 0;
757
    } else res.val.i = 1;
758
    res.type = T_BOOL;
759
    break;
760
  case '0':
761
    debug( "No operation\n" );
762
    break;
763
  case P('p',','):
764
    ONEARG;
765
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
766
      log_commit(*L_INFO, &f_buf);
767

    
768
    switch (what->a2.i) {
769
    case F_QUITBIRD:
770
      die( "Filter asked me to die" );
771
    case F_ACCEPT:
772
      /* Should take care about turning ACCEPT into MODIFY */
773
    case F_ERROR:
774
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
775
      res.type = T_RETURN;
776
      res.val.i = what->a2.i;
777
      return res;        /* We have to return now, no more processing. */
778
    case F_NONL:
779
    case F_NOP:
780
      break;
781
    default:
782
      bug( "unknown return type: Can't happen");
783
    }
784
    break;
785
  case 'a':        /* rta access */
786
    {
787
      ACCESS_RTE;
788
      struct rta *rta = (*f_rte)->attrs;
789
      res.type = what->aux;
790

    
791
      switch (what->a2.i)
792
      {
793
      case SA_FROM:        res.val.px.ip = rta->from; break;
794
      case SA_GW:        res.val.px.ip = rta->gw; break;
795
      case SA_NET:        res.val.px.ip = net_prefix((*f_rte)->net->n.addr);
796
                        res.val.px.len = net_pxlen((*f_rte)->net->n.addr); break;
797
      case SA_PROTO:        res.val.s = rta->src->proto->name; break;
798
      case SA_SOURCE:        res.val.i = rta->source; break;
799
      case SA_SCOPE:        res.val.i = rta->scope; break;
800
      case SA_CAST:        res.val.i = rta->cast; break;
801
      case SA_DEST:        res.val.i = rta->dest; break;
802
      case SA_IFNAME:        res.val.s = rta->iface ? rta->iface->name : ""; break;
803
      case SA_IFINDEX:        res.val.i = rta->iface ? rta->iface->index : 0; break;
804

    
805
      default:
806
        bug("Invalid static attribute access (%x)", res.type);
807
      }
808
    }
809
    break;
810
  case P('a','S'):
811
    ACCESS_RTE;
812
    ONEARG;
813
    if (what->aux != v1.type)
814
      runtime( "Attempt to set static attribute to incompatible type" );
815

    
816
    f_rta_cow();
817
    {
818
      struct rta *rta = (*f_rte)->attrs;
819

    
820
      switch (what->a2.i)
821
      {
822
      case SA_FROM:
823
        rta->from = v1.val.px.ip;
824
        break;
825

    
826
      case SA_GW:
827
        {
828
          ip_addr ip = v1.val.px.ip;
829
          neighbor *n = neigh_find(rta->src->proto, &ip, 0);
830
          if (!n || (n->scope == SCOPE_HOST))
831
            runtime( "Invalid gw address" );
832

    
833
          rta->dest = RTD_ROUTER;
834
          rta->gw = ip;
835
          rta->iface = n->iface;
836
          rta->nexthops = NULL;
837
          rta->hostentry = NULL;
838
        }
839
        break;
840

    
841
      case SA_SCOPE:
842
        rta->scope = v1.val.i;
843
        break;
844

    
845
      case SA_DEST:
846
        i = v1.val.i;
847
        if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
848
          runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
849

    
850
        rta->dest = i;
851
        rta->gw = IPA_NONE;
852
        rta->iface = NULL;
853
        rta->nexthops = NULL;
854
        rta->hostentry = NULL;
855
        break;
856

    
857
      default:
858
        bug("Invalid static attribute access (%x)", res.type);
859
      }
860
    }
861
    break;
862
  case P('e','a'):        /* Access to extended attributes */
863
    ACCESS_RTE;
864
    {
865
      eattr *e = NULL;
866
      u16 code = what->a2.i;
867

    
868
      if (!(f_flags & FF_FORCE_TMPATTR))
869
        e = ea_find((*f_rte)->attrs->eattrs, code);
870
      if (!e)
871
        e = ea_find((*f_tmp_attrs), code);
872
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
873
        e = ea_find((*f_rte)->attrs->eattrs, code);
874

    
875
      if (!e) {
876
        /* A special case: undefined int_set looks like empty int_set */
877
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
878
          res.type = T_CLIST;
879
          res.val.ad = adata_empty(f_pool, 0);
880
          break;
881
        }
882

    
883
        /* The same special case for ec_set */
884
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
885
          res.type = T_ECLIST;
886
          res.val.ad = adata_empty(f_pool, 0);
887
          break;
888
        }
889

    
890
        /* Undefined value */
891
        res.type = T_VOID;
892
        break;
893
      }
894

    
895
      switch (what->aux & EAF_TYPE_MASK) {
896
      case EAF_TYPE_INT:
897
        res.type = T_INT;
898
        res.val.i = e->u.data;
899
        break;
900
      case EAF_TYPE_ROUTER_ID:
901
        res.type = T_QUAD;
902
        res.val.i = e->u.data;
903
        break;
904
      case EAF_TYPE_OPAQUE:
905
        res.type = T_ENUM_EMPTY;
906
        res.val.i = 0;
907
        break;
908
      case EAF_TYPE_IP_ADDRESS:
909
        res.type = T_IP;
910
        struct adata * ad = e->u.ptr;
911
        res.val.px.ip = * (ip_addr *) ad->data;
912
        break;
913
      case EAF_TYPE_AS_PATH:
914
        res.type = T_PATH;
915
        res.val.ad = e->u.ptr;
916
        break;
917
      case EAF_TYPE_BITFIELD:
918
        res.type = T_BOOL;
919
        res.val.i = !!(e->u.data & BITFIELD_MASK(what));
920
        break;
921
      case EAF_TYPE_INT_SET:
922
        res.type = T_CLIST;
923
        res.val.ad = e->u.ptr;
924
        break;
925
      case EAF_TYPE_EC_SET:
926
        res.type = T_ECLIST;
927
        res.val.ad = e->u.ptr;
928
        break;
929
      case EAF_TYPE_UNDEF:
930
        res.type = T_VOID;
931
        break;
932
      default:
933
        bug("Unknown type in e,a");
934
      }
935
    }
936
    break;
937
  case P('e','S'):
938
    ACCESS_RTE;
939
    ONEARG;
940
    {
941
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
942
      u16 code = what->a2.i;
943

    
944
      l->next = NULL;
945
      l->flags = EALF_SORTED;
946
      l->count = 1;
947
      l->attrs[0].id = code;
948
      l->attrs[0].flags = 0;
949
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
950

    
951
      switch (what->aux & EAF_TYPE_MASK) {
952
      case EAF_TYPE_INT:
953
        if (v1.type != T_INT)
954
          runtime( "Setting int attribute to non-int value" );
955
        l->attrs[0].u.data = v1.val.i;
956
        break;
957

    
958
      case EAF_TYPE_ROUTER_ID:
959
#ifndef IPV6
960
        /* IP->Quad implicit conversion */
961
        if (v1.type == T_IP) {
962
          l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
963
          break;
964
        }
965
#endif
966
        /* T_INT for backward compatibility */
967
        if ((v1.type != T_QUAD) && (v1.type != T_INT))
968
          runtime( "Setting quad attribute to non-quad value" );
969
        l->attrs[0].u.data = v1.val.i;
970
        break;
971

    
972
      case EAF_TYPE_OPAQUE:
973
        runtime( "Setting opaque attribute is not allowed" );
974
        break;
975
      case EAF_TYPE_IP_ADDRESS:
976
        if (v1.type != T_IP)
977
          runtime( "Setting ip attribute to non-ip value" );
978
        int len = sizeof(ip_addr);
979
        struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
980
        ad->length = len;
981
        (* (ip_addr *) ad->data) = v1.val.px.ip;
982
        l->attrs[0].u.ptr = ad;
983
        break;
984
      case EAF_TYPE_AS_PATH:
985
        if (v1.type != T_PATH)
986
          runtime( "Setting path attribute to non-path value" );
987
        l->attrs[0].u.ptr = v1.val.ad;
988
        break;
989
      case EAF_TYPE_BITFIELD:
990
        if (v1.type != T_BOOL)
991
          runtime( "Setting bit in bitfield attribute to non-bool value" );
992
        {
993
          /* First, we have to find the old value */
994
          eattr *e = NULL;
995
          if (!(f_flags & FF_FORCE_TMPATTR))
996
            e = ea_find((*f_rte)->attrs->eattrs, code);
997
          if (!e)
998
            e = ea_find((*f_tmp_attrs), code);
999
          if ((!e) && (f_flags & FF_FORCE_TMPATTR))
1000
            e = ea_find((*f_rte)->attrs->eattrs, code);
1001
          u32 data = e ? e->u.data : 0;
1002

    
1003
          if (v1.val.i)
1004
            l->attrs[0].u.data = data | BITFIELD_MASK(what);
1005
          else
1006
            l->attrs[0].u.data = data & ~BITFIELD_MASK(what);;
1007
        }
1008
        break;
1009
      case EAF_TYPE_INT_SET:
1010
        if (v1.type != T_CLIST)
1011
          runtime( "Setting clist attribute to non-clist value" );
1012
        l->attrs[0].u.ptr = v1.val.ad;
1013
        break;
1014
      case EAF_TYPE_EC_SET:
1015
        if (v1.type != T_ECLIST)
1016
          runtime( "Setting eclist attribute to non-eclist value" );
1017
        l->attrs[0].u.ptr = v1.val.ad;
1018
        break;
1019
      case EAF_TYPE_UNDEF:
1020
        if (v1.type != T_VOID)
1021
          runtime( "Setting void attribute to non-void value" );
1022
        l->attrs[0].u.data = 0;
1023
        break;
1024
      default: bug("Unknown type in e,S");
1025
      }
1026

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

    
1079
    as = 0;
1080
    as_path_get_first(v1.val.ad, &as);
1081
    res.type = T_INT;
1082
    res.val.i = as;
1083
    break;
1084
  case P('a','l'):        /* Get last ASN from AS PATH */
1085
    ONEARG;
1086
    if (v1.type != T_PATH)
1087
      runtime( "AS path expected" );
1088

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

    
1124
      res = interpret(t->data);
1125
      if (res.type & T_RETURN)
1126
        return res;
1127
    }
1128
    break;
1129
  case P('i','M'): /* IP.MASK(val) */
1130
    TWOARGS;
1131
    if (v2.type != T_INT)
1132
      runtime( "Integer expected");
1133
    if (v1.type != T_IP)
1134
      runtime( "You can mask only IP addresses" );
1135
    {
1136
      ip_addr mask = ipa_mkmask(v2.val.i);
1137
      res.type = T_IP;
1138
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
1139
    }
1140
    break;
1141

    
1142
  case 'E':        /* Create empty attribute */
1143
    res.type = what->aux;
1144
    res.val.ad = adata_empty(f_pool, 0);
1145
    break;
1146
  case P('A','p'):        /* Path prepend */
1147
    TWOARGS;
1148
    if (v1.type != T_PATH)
1149
      runtime("Can't prepend to non-path");
1150
    if (v2.type != T_INT)
1151
      runtime("Can't prepend non-integer");
1152

    
1153
    res.type = T_PATH;
1154
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
1155
    break;
1156

    
1157
  case P('C','a'):        /* (Extended) Community list add or delete */
1158
    TWOARGS;
1159
    if (v1.type == T_PATH)
1160
    {
1161
      struct f_tree *set = NULL;
1162
      u32 key = 0;
1163
      int pos;
1164

    
1165
      if (v2.type == T_INT)
1166
        key = v2.val.i;
1167
      else if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
1168
        set = v2.val.t;
1169
      else
1170
        runtime("Can't delete non-integer (set)");
1171

    
1172
      switch (what->aux)
1173
      {
1174
      case 'a':        runtime("Can't add to path");
1175
      case 'd':        pos = 0; break;
1176
      case 'f':        pos = 1; break;
1177
      default:        bug("unknown Ca operation");
1178
      }
1179

    
1180
      if (pos && !set)
1181
        runtime("Can't filter integer");
1182

    
1183
      res.type = T_PATH;
1184
      res.val.ad = as_path_filter(f_pool, v1.val.ad, set, key, pos);
1185
    }
1186
    else if (v1.type == T_CLIST)
1187
    {
1188
      /* Community (or cluster) list */
1189
      struct f_val dummy;
1190
      int arg_set = 0;
1191
      uint n = 0;
1192

    
1193
      if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
1194
        n = v2.val.i;
1195
#ifndef IPV6
1196
      /* IP->Quad implicit conversion */
1197
      else if (v2.type == T_IP)
1198
        n = ipa_to_u32(v2.val.px.ip);
1199
#endif
1200
      else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
1201
        arg_set = 1;
1202
      else if (v2.type == T_CLIST)
1203
        arg_set = 2;
1204
      else
1205
        runtime("Can't add/delete non-pair");
1206

    
1207
      res.type = T_CLIST;
1208
      switch (what->aux)
1209
      {
1210
      case 'a':
1211
        if (arg_set == 1)
1212
          runtime("Can't add set");
1213
        else if (!arg_set)
1214
          res.val.ad = int_set_add(f_pool, v1.val.ad, n);
1215
        else
1216
          res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
1217
        break;
1218

    
1219
      case 'd':
1220
        if (!arg_set)
1221
          res.val.ad = int_set_del(f_pool, v1.val.ad, n);
1222
        else
1223
          res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
1224
        break;
1225

    
1226
      case 'f':
1227
        if (!arg_set)
1228
          runtime("Can't filter pair");
1229
        res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 1);
1230
        break;
1231

    
1232
      default:
1233
        bug("unknown Ca operation");
1234
      }
1235
    }
1236
    else if (v1.type == T_ECLIST)
1237
    {
1238
      /* Extended community list */
1239
      int arg_set = 0;
1240

    
1241
      /* v2.val is either EC or EC-set */
1242
      if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
1243
        arg_set = 1;
1244
      else if (v2.type == T_ECLIST)
1245
        arg_set = 2;
1246
      else if (v2.type != T_EC)
1247
        runtime("Can't add/delete non-pair");
1248

    
1249
      res.type = T_ECLIST;
1250
      switch (what->aux)
1251
      {
1252
      case 'a':
1253
        if (arg_set == 1)
1254
          runtime("Can't add set");
1255
        else if (!arg_set)
1256
          res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
1257
        else
1258
          res.val.ad = ec_set_union(f_pool, v1.val.ad, v2.val.ad);
1259
        break;
1260

    
1261
      case 'd':
1262
        if (!arg_set)
1263
          res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
1264
        else
1265
          res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 0);
1266
        break;
1267

    
1268
      case 'f':
1269
        if (!arg_set)
1270
          runtime("Can't filter ec");
1271
        res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 1);
1272
        break;
1273

    
1274
      default:
1275
        bug("unknown Ca operation");
1276
      }
1277
    }
1278
    else
1279
      runtime("Can't add/delete to non-(e)clist");
1280

    
1281
    break;
1282

    
1283
  case P('R','C'):        /* ROA Check */
1284
    if (what->arg1)
1285
    {
1286
      TWOARGS;
1287
      if ((v1.type != T_PREFIX) || (v2.type != T_INT))
1288
        runtime("Invalid argument to roa_check()");
1289

    
1290
      as = v2.val.i;
1291
    }
1292
    else
1293
    {
1294
      ACCESS_RTE;
1295
      v1.val.px.ip = net_prefix((*f_rte)->net->n.addr);
1296
      v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
1297

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

    
1302
      if (!e || e->type != EAF_TYPE_AS_PATH)
1303
        runtime("Missing AS_PATH attribute");
1304

    
1305
      as_path_get_last(e->u.ptr, &as);
1306
    }
1307

    
1308
    struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
1309
    if (!rtc->table)
1310
      runtime("Missing ROA table");
1311

    
1312
    res.type = T_ENUM_ROA;
1313
    res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
1314
    break;
1315

    
1316
  default:
1317
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
1318
  }
1319
  if (what->next)
1320
    return interpret(what->next);
1321
  return res;
1322
}
1323

    
1324
#undef ARG
1325
#define ARG(x,y) \
1326
        if (!i_same(f1->y, f2->y)) \
1327
                return 0;
1328

    
1329
#define ONEARG ARG(v1, a1.p)
1330
#define TWOARGS ARG(v1, a1.p) \
1331
                ARG(v2, a2.p)
1332

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

    
1335
/*
1336
 * i_same - function that does real comparing of instruction trees, you should call filter_same from outside
1337
 */
1338
int
1339
i_same(struct f_inst *f1, struct f_inst *f2)
1340
{
1341
  if ((!!f1) != (!!f2))
1342
    return 0;
1343
  if (!f1)
1344
    return 1;
1345
  if (f1->aux != f2->aux)
1346
    return 0;
1347
  if (f1->code != f2->code)
1348
    return 0;
1349
  if (f1 == f2)                /* It looks strange, but it is possible with call rewriting trickery */
1350
    return 1;
1351

    
1352
  switch(f1->code) {
1353
  case ',': /* fall through */
1354
  case '+':
1355
  case '-':
1356
  case '*':
1357
  case '/':
1358
  case '|':
1359
  case '&':
1360
  case P('m','p'):
1361
  case P('m','c'):
1362
  case P('!','='):
1363
  case P('=','='):
1364
  case '<':
1365
  case P('<','='): TWOARGS; break;
1366

    
1367
  case '!': ONEARG; break;
1368
  case '~': TWOARGS; break;
1369
  case P('d','e'): ONEARG; break;
1370

    
1371
  case 's':
1372
    ARG(v2, a2.p);
1373
    {
1374
      struct symbol *s1, *s2;
1375
      s1 = f1->a1.p;
1376
      s2 = f2->a1.p;
1377
      if (strcmp(s1->name, s2->name))
1378
        return 0;
1379
      if (s1->class != s2->class)
1380
        return 0;
1381
    }
1382
    break;
1383

    
1384
  case 'c':
1385
    switch (f1->aux) {
1386

    
1387
    case T_PREFIX_SET:
1388
      if (!trie_same(f1->a2.p, f2->a2.p))
1389
        return 0;
1390
      break;
1391

    
1392
    case T_SET:
1393
      if (!same_tree(f1->a2.p, f2->a2.p))
1394
        return 0;
1395
      break;
1396

    
1397
    case T_STRING:
1398
      if (strcmp(f1->a2.p, f2->a2.p))
1399
        return 0;
1400
      break;
1401

    
1402
    default:
1403
      A2_SAME;
1404
    }
1405
    break;
1406

    
1407
  case 'C':
1408
    if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
1409
      return 0;
1410
    break;
1411

    
1412
  case 'V':
1413
    if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
1414
      return 0;
1415
    break;
1416
  case 'p': case 'L': ONEARG; break;
1417
  case '?': TWOARGS; break;
1418
  case '0': case 'E': break;
1419
  case P('p',','): ONEARG; A2_SAME; break;
1420
  case 'P':
1421
  case 'a': A2_SAME; break;
1422
  case P('e','a'): A2_SAME; break;
1423
  case P('P','S'):
1424
  case P('a','S'):
1425
  case P('e','S'): ONEARG; A2_SAME; break;
1426

    
1427
  case 'r': ONEARG; break;
1428
  case P('c','p'): ONEARG; break;
1429
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
1430
             ONEARG;
1431
             if (!i_same(f1->a2.p, f2->a2.p))
1432
               return 0;
1433
             f2->a2.p = f1->a2.p;
1434
             break;
1435
  case P('c','v'): break; /* internal instruction */
1436
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
1437
  case P('i','M'): TWOARGS; break;
1438
  case P('A','p'): TWOARGS; break;
1439
  case P('C','a'): TWOARGS; break;
1440
  case P('a','f'):
1441
  case P('a','l'): ONEARG; break;
1442
  case P('R','C'):
1443
    TWOARGS;
1444
    /* Does not really make sense - ROA check resuls may change anyway */
1445
    if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
1446
               ((struct f_inst_roa_check *) f2)->rtc->name))
1447
      return 0;
1448
    break;
1449
  default:
1450
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
1451
  }
1452
  return i_same(f1->next, f2->next);
1453
}
1454

    
1455
/**
1456
 * f_run - run a filter for a route
1457
 * @filter: filter to run
1458
 * @rte: route being filtered, may be modified
1459
 * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
1460
 * @tmp_pool: all filter allocations go from this pool
1461
 * @flags: flags
1462
 *
1463
 * If filter needs to modify the route, there are several
1464
 * posibilities. @rte might be read-only (with REF_COW flag), in that
1465
 * case rw copy is obtained by rte_cow() and @rte is replaced. If
1466
 * @rte is originally rw, it may be directly modified (and it is never
1467
 * copied).
1468
 *
1469
 * The returned rte may reuse the (possibly cached, cloned) rta, or
1470
 * (if rta was modificied) contains a modified uncached rta, which
1471
 * uses parts allocated from @tmp_pool and parts shared from original
1472
 * rta. There is one exception - if @rte is rw but contains a cached
1473
 * rta and that is modified, rta in returned rte is also cached.
1474
 *
1475
 * Ownership of cached rtas is consistent with rte, i.e.
1476
 * if a new rte is returned, it has its own clone of cached rta
1477
 * (and cached rta of read-only source rte is intact), if rte is
1478
 * modified in place, old cached rta is possibly freed.
1479
 */
1480
int
1481
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
1482
{
1483
  if (filter == FILTER_ACCEPT)
1484
    return F_ACCEPT;
1485

    
1486
  if (filter == FILTER_REJECT)
1487
    return F_REJECT;
1488

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

    
1492
  f_rte = rte;
1493
  f_old_rta = NULL;
1494
  f_tmp_attrs = tmp_attrs;
1495
  f_pool = tmp_pool;
1496
  f_flags = flags;
1497

    
1498
  LOG_BUFFER_INIT(f_buf);
1499

    
1500
  struct f_val res = interpret(filter->root);
1501

    
1502
  if (f_old_rta) {
1503
    /*
1504
     * Cached rta was modified and f_rte contains now an uncached one,
1505
     * sharing some part with the cached one. The cached rta should
1506
     * be freed (if rte was originally COW, f_old_rta is a clone
1507
     * obtained during rte_cow()).
1508
     *
1509
     * This also implements the exception mentioned in f_run()
1510
     * description. The reason for this is that rta reuses parts of
1511
     * f_old_rta, and these may be freed during rta_free(f_old_rta).
1512
     * This is not the problem if rte was COW, because original rte
1513
     * also holds the same rta.
1514
     */
1515
    if (!rte_cow)
1516
      (*f_rte)->attrs = rta_lookup((*f_rte)->attrs);
1517

    
1518
    rta_free(f_old_rta);
1519
  }
1520

    
1521

    
1522
  if (res.type != T_RETURN) {
1523
    log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
1524
    return F_ERROR;
1525
  }
1526
  DBG( "done (%u)\n", res.val.i );
1527
  return res.val.i;
1528
}
1529

    
1530
/* TODO: perhaps we could integrate f_eval(), f_eval_rte() and f_run() */
1531

    
1532
struct f_val
1533
f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
1534
{
1535
  struct ea_list *tmp_attrs = NULL;
1536

    
1537
  f_rte = rte;
1538
  f_old_rta = NULL;
1539
  f_tmp_attrs = &tmp_attrs;
1540
  f_pool = tmp_pool;
1541
  f_flags = 0;
1542

    
1543
  LOG_BUFFER_INIT(f_buf);
1544

    
1545
  /* Note that in this function we assume that rte->attrs is private / uncached */
1546
  struct f_val res = interpret(expr);
1547

    
1548
  /* Hack to include EAF_TEMP attributes to the main list */
1549
  (*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs);
1550

    
1551
  return res;
1552
}
1553

    
1554
struct f_val
1555
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
1556
{
1557
  f_flags = 0;
1558
  f_tmp_attrs = NULL;
1559
  f_rte = NULL;
1560
  f_pool = tmp_pool;
1561

    
1562
  LOG_BUFFER_INIT(f_buf);
1563

    
1564
  return interpret(expr);
1565
}
1566

    
1567
uint
1568
f_eval_int(struct f_inst *expr)
1569
{
1570
  /* Called independently in parse-time to eval expressions */
1571
  struct f_val res = f_eval(expr, cfg_mem);
1572

    
1573
  if (res.type != T_INT)
1574
    cf_error("Integer expression expected");
1575

    
1576
  return res.val.i;
1577
}
1578

    
1579
u32
1580
f_eval_asn(struct f_inst *expr)
1581
{
1582
  /* Called as a part of another interpret call, therefore no log_reset() */
1583
  struct f_val res = interpret(expr);
1584
  return (res.type == T_INT) ? res.val.i : 0;
1585
}
1586

    
1587
/**
1588
 * filter_same - compare two filters
1589
 * @new: first filter to be compared
1590
 * @old: second filter to be compared, notice that this filter is
1591
 * damaged while comparing.
1592
 *
1593
 * Returns 1 in case filters are same, otherwise 0. If there are
1594
 * underlying bugs, it will rather say 0 on same filters than say
1595
 * 1 on different.
1596
 */
1597
int
1598
filter_same(struct filter *new, struct filter *old)
1599
{
1600
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
1601
    return 1;
1602
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
1603
      new == FILTER_ACCEPT || new == FILTER_REJECT)
1604
    return 0;
1605
  return i_same(new->root, old->root);
1606
}