Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 5e173e9f

History | View | Annotate | Download (38.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 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 val_is_ip4(const struct f_val v)
94
{ return (v.type == T_IP) && ipa_is_ip4(v.val.ip); }
95

    
96
/**
97
 * val_compare - compare two values
98
 * @v1: first value
99
 * @v2: second value
100
 *
101
 * Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
102
 * error. Tree module relies on this giving consistent results so
103
 * that it can be used for building balanced trees.
104
 */
105
int
106
val_compare(struct f_val v1, struct f_val v2)
107
{
108
  if (v1.type != v2.type) {
109
    if (v1.type == T_VOID)        /* Hack for else */
110
      return -1;
111
    if (v2.type == T_VOID)
112
      return 1;
113

    
114
#ifndef IPV6
115
    /* IP->Quad implicit conversion */
116
    if ((v1.type == T_QUAD) && val_is_ip4(v2))
117
      return uint_cmp(v1.val.i, ipa_to_u32(v2.val.ip));
118
    if (val_is_ip4(v1) && (v2.type == T_QUAD))
119
      return uint_cmp(ipa_to_u32(v1.val.ip), v2.val.i);
120
#endif
121

    
122
    debug( "Types do not match in val_compare\n" );
123
    return CMP_ERROR;
124
  }
125

    
126
  switch (v1.type) {
127
  case T_VOID:
128
    return 0;
129
  case T_ENUM:
130
  case T_INT:
131
  case T_BOOL:
132
  case T_PAIR:
133
  case T_QUAD:
134
    return uint_cmp(v1.val.i, v2.val.i);
135
  case T_EC:
136
    return u64_cmp(v1.val.ec, v2.val.ec);
137
  case T_IP:
138
    return ipa_compare(v1.val.ip, v2.val.ip);
139
  case T_NET:
140
    return net_compare(v1.val.net, v2.val.net);
141
  case T_STRING:
142
    return strcmp(v1.val.s, v2.val.s);
143
  default:
144
    return CMP_ERROR;
145
  }
146
}
147

    
148
static int
149
pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2)
150
{
151
  while (m1 && m2)
152
  {
153
    if ((m1->kind != m2->kind) || (m1->val != m2->val))
154
      return 0;
155

    
156
    m1 = m1->next;
157
    m2 = m2->next;
158
  }
159

    
160
 return !m1 && !m2;
161
}
162

    
163
/**
164
 * val_same - compare two values
165
 * @v1: first value
166
 * @v2: second value
167
 *
168
 * Compares two values and returns 1 if they are same and 0 if not.
169
 * Comparison of values of different types is valid and returns 0.
170
 */
171
int
172
val_same(struct f_val v1, struct f_val v2)
173
{
174
  int rc;
175

    
176
  rc = val_compare(v1, v2);
177
  if (rc != CMP_ERROR)
178
    return !rc;
179

    
180
  if (v1.type != v2.type)
181
    return 0;
182

    
183
  switch (v1.type) {
184
  case T_PATH_MASK:
185
    return pm_path_same(v1.val.path_mask, v2.val.path_mask);
186
  case T_PATH:
187
  case T_CLIST:
188
  case T_ECLIST:
189
    return adata_same(v1.val.ad, v2.val.ad);
190
  case T_SET:
191
    return same_tree(v1.val.t, v2.val.t);
192
  case T_PREFIX_SET:
193
    return trie_same(v1.val.ti, v2.val.ti);
194
  default:
195
    bug("Invalid type in val_same(): %x", v1.type);
196
  }
197
}
198

    
199
static int
200
clist_set_type(struct f_tree *set, struct f_val *v)
201
{
202
 switch (set->from.type) {
203
  case T_PAIR:
204
    v->type = T_PAIR;
205
    return 1;
206
  case T_QUAD:
207
#ifndef IPV6
208
  case T_IP:
209
#endif
210
    v->type = T_QUAD;
211
    return 1;
212
    break;
213
  default:
214
    v->type = T_VOID;
215
    return 0;
216
  }
217
}
218

    
219
static inline int
220
eclist_set_type(struct f_tree *set)
221
{ return set->from.type == T_EC; }
222

    
223
static int
224
clist_match_set(struct adata *clist, struct f_tree *set)
225
{
226
  if (!clist)
227
    return 0;
228

    
229
  struct f_val v;
230
  if (!clist_set_type(set, &v))
231
    return CMP_ERROR;
232

    
233
  u32 *l = (u32 *) clist->data;
234
  u32 *end = l + clist->length/4;
235

    
236
  while (l < end) {
237
    v.val.i = *l++;
238
    if (find_tree(set, v))
239
      return 1;
240
  }
241
  return 0;
242
}
243

    
244
static int
245
eclist_match_set(struct adata *list, struct f_tree *set)
246
{
247
  if (!list)
248
    return 0;
249

    
250
  if (!eclist_set_type(set))
251
    return CMP_ERROR;
252

    
253
  struct f_val v;
254
  u32 *l = int_set_get_data(list);
255
  int len = int_set_get_size(list);
256
  int i;
257

    
258
  v.type = T_EC;
259
  for (i = 0; i < len; i += 2) {
260
    v.val.ec = ec_get(l, i);
261
    if (find_tree(set, v))
262
      return 1;
263
  }
264

    
265
  return 0;
266
}
267

    
268
static struct adata *
269
clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
270
{
271
  if (!list)
272
    return NULL;
273

    
274
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
275
  struct f_val v;
276
  if (tree)
277
    clist_set_type(set.val.t, &v);
278
  else
279
    v.type = T_PAIR;
280

    
281
  int len = int_set_get_size(list);
282
  u32 *l = int_set_get_data(list);
283
  u32 tmp[len];
284
  u32 *k = tmp;
285
  u32 *end = l + len;
286

    
287
  while (l < end) {
288
    v.val.i = *l++;
289
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
290
    if ((tree ? !!find_tree(set.val.t, v) : int_set_contains(set.val.ad, v.val.i)) == pos)
291
      *k++ = v.val.i;
292
  }
293

    
294
  int nl = (k - tmp) * 4;
295
  if (nl == list->length)
296
    return list;
297

    
298
  struct adata *res = adata_empty(pool, nl);
299
  memcpy(res->data, tmp, nl);
300
  return res;
301
}
302

    
303
static struct adata *
304
eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
305
{
306
  if (!list)
307
    return NULL;
308

    
309
  int tree = (set.type == T_SET);        /* 1 -> set is T_SET, 0 -> set is T_CLIST */
310
  struct f_val v;
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
  int i;
317

    
318
  v.type = T_EC;
319
  for (i = 0; i < len; i += 2) {
320
    v.val.ec = ec_get(l, i);
321
    /* pos && member(val, set) || !pos && !member(val, set),  member() depends on tree */
322
    if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
323
      *k++ = l[i];
324
      *k++ = l[i+1];
325
    }
326
  }
327

    
328
  int nl = (k - tmp) * 4;
329
  if (nl == list->length)
330
    return list;
331

    
332
  struct adata *res = adata_empty(pool, nl);
333
  memcpy(res->data, tmp, nl);
334
  return res;
335
}
336

    
337
/**
338
 * val_in_range - implement |~| operator
339
 * @v1: element
340
 * @v2: set
341
 *
342
 * Checks if @v1 is element (|~| operator) of @v2.
343
 */
344
static int
345
val_in_range(struct f_val v1, struct f_val v2)
346
{
347
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
348
    return as_path_match(v1.val.ad, v2.val.path_mask);
349

    
350
  if ((v1.type == T_INT) && (v2.type == T_PATH))
351
    return as_path_contains(v2.val.ad, v1.val.i, 1);
352

    
353
  if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
354
    return int_set_contains(v2.val.ad, v1.val.i);
355
#ifndef IPV6
356
  /* IP->Quad implicit conversion */
357
  if (val_is_ip4(v1) && (v2.type == T_CLIST))
358
    return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip));
359
#endif
360

    
361
  if ((v1.type == T_EC) && (v2.type == T_ECLIST))
362
    return ec_set_contains(v2.val.ad, v1.val.ec);
363

    
364
  if ((v1.type == T_STRING) && (v2.type == T_STRING))
365
    return patmatch(v2.val.s, v1.val.s);
366

    
367
  if ((v1.type == T_IP) && (v2.type == T_NET))
368
    return ipa_in_netX(v1.val.ip, v2.val.net);
369

    
370
  if ((v1.type == T_NET) && (v2.type == T_NET))
371
    return net_in_netX(v1.val.net, v2.val.net);
372

    
373
  if ((v1.type == T_NET) && (v2.type == T_PREFIX_SET))
374
    return trie_match_net(v2.val.ti, v1.val.net);
375

    
376
  if (v2.type != T_SET)
377
    return CMP_ERROR;
378

    
379
  /* With integrated Quad<->IP implicit conversion */
380
  if ((v1.type == v2.val.t->from.type) ||
381
      ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
382
    return !!find_tree(v2.val.t, v1);
383

    
384
  if (v1.type == T_CLIST)
385
    return clist_match_set(v1.val.ad, v2.val.t);
386

    
387
  if (v1.type == T_ECLIST)
388
    return eclist_match_set(v1.val.ad, v2.val.t);
389

    
390
  if (v1.type == T_PATH)
391
    return as_path_match_set(v1.val.ad, v2.val.t);
392

    
393
  return CMP_ERROR;
394
}
395

    
396
/*
397
 * val_format - format filter value
398
 */
399
void
400
val_format(struct f_val v, buffer *buf)
401
{
402
  char buf2[1024];
403
  switch (v.type)
404
  {
405
  case T_VOID:        buffer_puts(buf, "(void)"); return;
406
  case T_BOOL:        buffer_puts(buf, v.val.i ? "TRUE" : "FALSE"); return;
407
  case T_INT:        buffer_print(buf, "%u", v.val.i); return;
408
  case T_STRING: buffer_print(buf, "%s", v.val.s); return;
409
  case T_IP:        buffer_print(buf, "%I", v.val.ip); return;
410
  case T_NET:   buffer_print(buf, "%N", v.val.net); return;
411
  case T_PAIR:        buffer_print(buf, "(%u,%u)", v.val.i >> 16, v.val.i & 0xffff); return;
412
  case T_QUAD:        buffer_print(buf, "%R", v.val.i); return;
413
  case T_EC:        ec_format(buf2, v.val.ec); buffer_print(buf, "%s", buf2); return;
414
  case T_PREFIX_SET: trie_format(v.val.ti, buf); return;
415
  case T_SET:        tree_format(v.val.t, buf); return;
416
  case T_ENUM:        buffer_print(buf, "(enum %x)%u", v.type, v.val.i); return;
417
  case T_PATH:        as_path_format(v.val.ad, buf2, 1000); buffer_print(buf, "(path %s)", buf2); return;
418
  case T_CLIST:        int_set_format(v.val.ad, 1, -1, buf2, 1000); buffer_print(buf, "(clist %s)", buf2); return;
419
  case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); buffer_print(buf, "(eclist %s)", buf2); return;
420
  case T_PATH_MASK: pm_format(v.val.path_mask, buf); return;
421
  default:        buffer_print(buf, "[unknown type %x]", v.type); return;
422
  }
423
}
424

    
425
static struct rte **f_rte;
426
static struct rta *f_old_rta;
427
static struct ea_list **f_tmp_attrs;
428
static struct linpool *f_pool;
429
static struct buffer f_buf;
430
static int f_flags;
431

    
432
static inline void f_rte_cow(void)
433
{
434
  *f_rte = rte_cow(*f_rte);
435
}
436

    
437
/*
438
 * rta_cow - prepare rta for modification by filter
439
 */
440
static void
441
f_rta_cow(void)
442
{
443
  if (!rta_is_cached((*f_rte)->attrs))
444
    return;
445

    
446
  /* Prepare to modify rte */
447
  f_rte_cow();
448

    
449
  /* Store old rta to free it later, it stores reference from rte_cow() */
450
  f_old_rta = (*f_rte)->attrs;
451

    
452
  /*
453
   * Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
454
   * with f_old_rta (they will be copied when the cached rta will be obtained
455
   * at the end of f_run()), also the lock of hostentry is inherited (we
456
   * suppose hostentry is not changed by filters).
457
   */
458
  (*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
459
}
460

    
461
static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
462

    
463
#define runtime(x) do { \
464
    log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
465
    res.type = T_RETURN; \
466
    res.val.i = F_ERROR; \
467
    return res; \
468
  } while(0)
469

    
470
#define ARG(x,y) \
471
        x = interpret(what->y); \
472
        if (x.type & T_RETURN) \
473
                return x;
474

    
475
#define ONEARG ARG(v1, a1.p)
476
#define TWOARGS ARG(v1, a1.p) \
477
                ARG(v2, a2.p)
478
#define TWOARGS_C TWOARGS \
479
                  if (v1.type != v2.type) \
480
                    runtime( "Can't operate with values of incompatible types" );
481
#define ACCESS_RTE \
482
  do { if (!f_rte) runtime("No route to access"); } while (0)
483

    
484
#define BITFIELD_MASK(what) \
485
  (1u << (what->a2.i >> 24))
486

    
487
/**
488
 * interpret
489
 * @what: filter to interpret
490
 *
491
 * Interpret given tree of filter instructions. This is core function
492
 * of filter system and does all the hard work.
493
 *
494
 * Each instruction has 4 fields: code (which is instruction code),
495
 * aux (which is extension to instruction code, typically type),
496
 * arg1 and arg2 - arguments. Depending on instruction, arguments
497
 * are either integers, or pointers to instruction trees. Common
498
 * instructions like +, that have two expressions as arguments use
499
 * TWOARGS macro to get both of them evaluated.
500
 *
501
 * &f_val structures are copied around, so there are no problems with
502
 * memory managment.
503
 */
504
static struct f_val
505
interpret(struct f_inst *what)
506
{
507
  struct symbol *sym;
508
  struct f_val v1, v2, res, *vp;
509
  unsigned u1, u2;
510
  int i;
511
  u32 as;
512

    
513
  res.type = T_VOID;
514
  if (!what)
515
    return res;
516

    
517
  switch(what->code) {
518
  case ',':
519
    TWOARGS;
520
    break;
521

    
522
/* Binary operators */
523
  case '+':
524
    TWOARGS_C;
525
    switch (res.type = v1.type) {
526
    case T_VOID: runtime( "Can't operate with values of type void" );
527
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
528
    default: runtime( "Usage of unknown type" );
529
    }
530
    break;
531
  case '-':
532
    TWOARGS_C;
533
    switch (res.type = v1.type) {
534
    case T_VOID: runtime( "Can't operate with values of type void" );
535
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
536
    default: runtime( "Usage of unknown type" );
537
    }
538
    break;
539
  case '*':
540
    TWOARGS_C;
541
    switch (res.type = v1.type) {
542
    case T_VOID: runtime( "Can't operate with values of type void" );
543
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
544
    default: runtime( "Usage of unknown type" );
545
    }
546
    break;
547
  case '/':
548
    TWOARGS_C;
549
    switch (res.type = v1.type) {
550
    case T_VOID: runtime( "Can't operate with values of type void" );
551
    case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
552
                      res.val.i = v1.val.i / v2.val.i; break;
553
    default: runtime( "Usage of unknown type" );
554
    }
555
    break;
556

    
557
  case '&':
558
  case '|':
559
    ARG(v1, a1.p);
560
    if (v1.type != T_BOOL)
561
      runtime( "Can't do boolean operation on non-booleans" );
562
    if (v1.val.i == (what->code == '|')) {
563
      res.type = T_BOOL;
564
      res.val.i = v1.val.i;
565
      break;
566
    }
567

    
568
    ARG(v2, a2.p);
569
    if (v2.type != T_BOOL)
570
      runtime( "Can't do boolean operation on non-booleans" );
571
    res.type = T_BOOL;
572
    res.val.i = v2.val.i;
573
    break;
574

    
575
  case P('m','p'):
576
    TWOARGS;
577
    if ((v1.type != T_INT) || (v2.type != T_INT))
578
      runtime( "Can't operate with value of non-integer type in pair constructor" );
579
    u1 = v1.val.i;
580
    u2 = v2.val.i;
581
    if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
582
      runtime( "Can't operate with value out of bounds in pair constructor" );
583
    res.val.i = (u1 << 16) | u2;
584
    res.type = T_PAIR;
585
    break;
586

    
587
  case P('m','c'):
588
    {
589
      TWOARGS;
590

    
591
      int check, ipv4_used;
592
      u32 key, val;
593

    
594
      if (v1.type == T_INT) {
595
        ipv4_used = 0; key = v1.val.i;
596
      }
597
      else if (v1.type == T_QUAD) {
598
        ipv4_used = 1; key = v1.val.i;
599
      }
600
#ifndef IPV6
601
      /* IP->Quad implicit conversion */
602
      else if (val_is_ip4(v1)) {
603
        ipv4_used = 1; key = ipa_to_u32(v1.val.ip);
604
      }
605
#endif
606
      else
607
        runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
608

    
609
      if (v2.type != T_INT)
610
        runtime("Can't operate with value of non-integer type in EC constructor");
611
      val = v2.val.i;
612

    
613
      res.type = T_EC;
614

    
615
      if (what->aux == EC_GENERIC) {
616
        check = 0; res.val.ec = ec_generic(key, val);
617
      }
618
      else if (ipv4_used) {
619
        check = 1; res.val.ec = ec_ip4(what->aux, key, val);
620
      }
621
      else if (key < 0x10000) {
622
        check = 0; res.val.ec = ec_as2(what->aux, key, val);
623
      }
624
      else {
625
        check = 1; res.val.ec = ec_as4(what->aux, key, val);
626
      }
627

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

    
631
      break;
632
    }
633

    
634
/* Relational operators */
635

    
636
#define COMPARE(x) \
637
    TWOARGS; \
638
    i = val_compare(v1, v2); \
639
    if (i==CMP_ERROR) \
640
      runtime( "Can't compare values of incompatible types" ); \
641
    res.type = T_BOOL; \
642
    res.val.i = (x); \
643
    break;
644

    
645
#define SAME(x) \
646
    TWOARGS; \
647
    i = val_same(v1, v2); \
648
    res.type = T_BOOL; \
649
    res.val.i = (x); \
650
    break;
651

    
652
  case P('!','='): SAME(!i);
653
  case P('=','='): SAME(i);
654
  case '<': COMPARE(i==-1);
655
  case P('<','='): COMPARE(i!=1);
656

    
657
  case '!':
658
    ONEARG;
659
    if (v1.type != T_BOOL)
660
      runtime( "Not applied to non-boolean" );
661
    res = v1;
662
    res.val.i = !res.val.i;
663
    break;
664

    
665
  case '~':
666
    TWOARGS;
667
    res.type = T_BOOL;
668
    res.val.i = val_in_range(v1, v2);
669
    if (res.val.i == CMP_ERROR)
670
      runtime( "~ applied on unknown type pair" );
671
    res.val.i = !!res.val.i;
672
    break;
673
  case P('d','e'):
674
    ONEARG;
675
    res.type = T_BOOL;
676
    res.val.i = (v1.type != T_VOID);
677
    break;
678

    
679
  /* Set to indirect value, a1 = variable, a2 = value */
680
  case 's':
681
    ARG(v2, a2.p);
682
    sym = what->a1.p;
683
    vp = sym->def;
684
    if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
685
#ifndef IPV6
686
      /* IP->Quad implicit conversion */
687
      if ((sym->class == (SYM_VARIABLE | T_QUAD)) && val_is_ip4(v2))
688
      {
689
        vp->type = T_QUAD;
690
        vp->val.i = ipa_to_u32(v2.val.ip);
691
        break;
692
      }
693
#endif
694
      runtime( "Assigning to variable of incompatible type" );
695
    }
696
    *vp = v2;
697
    break;
698

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

    
703
    if (res.type == T_PREFIX_SET)
704
      res.val.ti = what->a2.p;
705
    else if (res.type == T_SET)
706
      res.val.t = what->a2.p;
707
    else if (res.type == T_STRING)
708
      res.val.s = what->a2.p;
709
    else
710
      res.val.i = what->a2.i;
711
    break;
712
  case 'V':
713
  case 'C':
714
    res = * ((struct f_val *) what->a1.p);
715
    break;
716
  case 'p':
717
    ONEARG;
718
    val_format(v1, &f_buf);
719
    break;
720
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
721
    ONEARG;
722
    if (v1.type != T_BOOL)
723
      runtime( "If requires boolean expression" );
724
    if (v1.val.i) {
725
      ARG(res,a2.p);
726
      res.val.i = 0;
727
    } else res.val.i = 1;
728
    res.type = T_BOOL;
729
    break;
730
  case '0':
731
    debug( "No operation\n" );
732
    break;
733
  case P('p',','):
734
    ONEARG;
735
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
736
      log_commit(*L_INFO, &f_buf);
737

    
738
    switch (what->a2.i) {
739
    case F_QUITBIRD:
740
      die( "Filter asked me to die" );
741
    case F_ACCEPT:
742
      /* Should take care about turning ACCEPT into MODIFY */
743
    case F_ERROR:
744
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
745
      res.type = T_RETURN;
746
      res.val.i = what->a2.i;
747
      return res;        /* We have to return now, no more processing. */
748
    case F_NONL:
749
    case F_NOP:
750
      break;
751
    default:
752
      bug( "unknown return type: Can't happen");
753
    }
754
    break;
755
  case 'a':        /* rta access */
756
    {
757
      ACCESS_RTE;
758
      struct rta *rta = (*f_rte)->attrs;
759
      res.type = what->aux;
760

    
761
      switch (what->a2.i)
762
      {
763
      case SA_FROM:        res.val.ip = rta->from; break;
764
      case SA_GW:        res.val.ip = rta->gw; break;
765
      case SA_NET:        res.val.net = (*f_rte)->net->n.addr; break;
766
      case SA_PROTO:        res.val.s = rta->src->proto->name; break;
767
      case SA_SOURCE:        res.val.i = rta->source; break;
768
      case SA_SCOPE:        res.val.i = rta->scope; break;
769
      case SA_CAST:        res.val.i = rta->cast; break;
770
      case SA_DEST:        res.val.i = rta->dest; break;
771
      case SA_IFNAME:        res.val.s = rta->iface ? rta->iface->name : ""; break;
772
      case SA_IFINDEX:        res.val.i = rta->iface ? rta->iface->index : 0; break;
773

    
774
      default:
775
        bug("Invalid static attribute access (%x)", res.type);
776
      }
777
    }
778
    break;
779
  case P('a','S'):
780
    ACCESS_RTE;
781
    ONEARG;
782
    if (what->aux != v1.type)
783
      runtime( "Attempt to set static attribute to incompatible type" );
784

    
785
    f_rta_cow();
786
    {
787
      struct rta *rta = (*f_rte)->attrs;
788

    
789
      switch (what->a2.i)
790
      {
791
      case SA_FROM:
792
        rta->from = v1.val.ip;
793
        break;
794

    
795
      case SA_GW:
796
        {
797
          ip_addr ip = v1.val.ip;
798
          neighbor *n = neigh_find(rta->src->proto, &ip, 0);
799
          if (!n || (n->scope == SCOPE_HOST))
800
            runtime( "Invalid gw address" );
801

    
802
          rta->dest = RTD_ROUTER;
803
          rta->gw = ip;
804
          rta->iface = n->iface;
805
          rta->nexthops = NULL;
806
          rta->hostentry = NULL;
807
        }
808
        break;
809

    
810
      case SA_SCOPE:
811
        rta->scope = v1.val.i;
812
        break;
813

    
814
      case SA_DEST:
815
        i = v1.val.i;
816
        if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
817
          runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
818

    
819
        rta->dest = i;
820
        rta->gw = IPA_NONE;
821
        rta->iface = NULL;
822
        rta->nexthops = NULL;
823
        rta->hostentry = NULL;
824
        break;
825

    
826
      default:
827
        bug("Invalid static attribute access (%x)", res.type);
828
      }
829
    }
830
    break;
831
  case P('e','a'):        /* Access to extended attributes */
832
    ACCESS_RTE;
833
    {
834
      eattr *e = NULL;
835
      u16 code = what->a2.i;
836

    
837
      if (!(f_flags & FF_FORCE_TMPATTR))
838
        e = ea_find((*f_rte)->attrs->eattrs, code);
839
      if (!e)
840
        e = ea_find((*f_tmp_attrs), code);
841
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
842
        e = ea_find((*f_rte)->attrs->eattrs, code);
843

    
844
      if (!e) {
845
        /* A special case: undefined int_set looks like empty int_set */
846
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
847
          res.type = T_CLIST;
848
          res.val.ad = adata_empty(f_pool, 0);
849
          break;
850
        }
851

    
852
        /* The same special case for ec_set */
853
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
854
          res.type = T_ECLIST;
855
          res.val.ad = adata_empty(f_pool, 0);
856
          break;
857
        }
858

    
859
        /* Undefined value */
860
        res.type = T_VOID;
861
        break;
862
      }
863

    
864
      switch (what->aux & EAF_TYPE_MASK) {
865
      case EAF_TYPE_INT:
866
        res.type = T_INT;
867
        res.val.i = e->u.data;
868
        break;
869
      case EAF_TYPE_ROUTER_ID:
870
        res.type = T_QUAD;
871
        res.val.i = e->u.data;
872
        break;
873
      case EAF_TYPE_OPAQUE:
874
        res.type = T_ENUM_EMPTY;
875
        res.val.i = 0;
876
        break;
877
      case EAF_TYPE_IP_ADDRESS:
878
        res.type = T_IP;
879
        struct adata * ad = e->u.ptr;
880
        res.val.ip = * (ip_addr *) ad->data;
881
        break;
882
      case EAF_TYPE_AS_PATH:
883
        res.type = T_PATH;
884
        res.val.ad = e->u.ptr;
885
        break;
886
      case EAF_TYPE_BITFIELD:
887
        res.type = T_BOOL;
888
        res.val.i = !!(e->u.data & BITFIELD_MASK(what));
889
        break;
890
      case EAF_TYPE_INT_SET:
891
        res.type = T_CLIST;
892
        res.val.ad = e->u.ptr;
893
        break;
894
      case EAF_TYPE_EC_SET:
895
        res.type = T_ECLIST;
896
        res.val.ad = e->u.ptr;
897
        break;
898
      case EAF_TYPE_UNDEF:
899
        res.type = T_VOID;
900
        break;
901
      default:
902
        bug("Unknown type in e,a");
903
      }
904
    }
905
    break;
906
  case P('e','S'):
907
    ACCESS_RTE;
908
    ONEARG;
909
    {
910
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
911
      u16 code = what->a2.i;
912

    
913
      l->next = NULL;
914
      l->flags = EALF_SORTED;
915
      l->count = 1;
916
      l->attrs[0].id = code;
917
      l->attrs[0].flags = 0;
918
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
919

    
920
      switch (what->aux & EAF_TYPE_MASK) {
921
      case EAF_TYPE_INT:
922
        if (v1.type != T_INT)
923
          runtime( "Setting int attribute to non-int value" );
924
        l->attrs[0].u.data = v1.val.i;
925
        break;
926

    
927
      case EAF_TYPE_ROUTER_ID:
928
#ifndef IPV6
929
        /* IP->Quad implicit conversion */
930
        if (val_is_ip4(v1)) {
931
          l->attrs[0].u.data = ipa_to_u32(v1.val.ip);
932
          break;
933
        }
934
#endif
935
        /* T_INT for backward compatibility */
936
        if ((v1.type != T_QUAD) && (v1.type != T_INT))
937
          runtime( "Setting quad attribute to non-quad value" );
938
        l->attrs[0].u.data = v1.val.i;
939
        break;
940

    
941
      case EAF_TYPE_OPAQUE:
942
        runtime( "Setting opaque attribute is not allowed" );
943
        break;
944
      case EAF_TYPE_IP_ADDRESS:
945
        if (v1.type != T_IP)
946
          runtime( "Setting ip attribute to non-ip value" );
947
        int len = sizeof(ip_addr);
948
        struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
949
        ad->length = len;
950
        (* (ip_addr *) ad->data) = v1.val.ip;
951
        l->attrs[0].u.ptr = ad;
952
        break;
953
      case EAF_TYPE_AS_PATH:
954
        if (v1.type != T_PATH)
955
          runtime( "Setting path attribute to non-path value" );
956
        l->attrs[0].u.ptr = v1.val.ad;
957
        break;
958
      case EAF_TYPE_BITFIELD:
959
        if (v1.type != T_BOOL)
960
          runtime( "Setting bit in bitfield attribute to non-bool value" );
961
        {
962
          /* First, we have to find the old value */
963
          eattr *e = NULL;
964
          if (!(f_flags & FF_FORCE_TMPATTR))
965
            e = ea_find((*f_rte)->attrs->eattrs, code);
966
          if (!e)
967
            e = ea_find((*f_tmp_attrs), code);
968
          if ((!e) && (f_flags & FF_FORCE_TMPATTR))
969
            e = ea_find((*f_rte)->attrs->eattrs, code);
970
          u32 data = e ? e->u.data : 0;
971

    
972
          if (v1.val.i)
973
            l->attrs[0].u.data = data | BITFIELD_MASK(what);
974
          else
975
            l->attrs[0].u.data = data & ~BITFIELD_MASK(what);;
976
        }
977
        break;
978
      case EAF_TYPE_INT_SET:
979
        if (v1.type != T_CLIST)
980
          runtime( "Setting clist attribute to non-clist value" );
981
        l->attrs[0].u.ptr = v1.val.ad;
982
        break;
983
      case EAF_TYPE_EC_SET:
984
        if (v1.type != T_ECLIST)
985
          runtime( "Setting eclist attribute to non-eclist value" );
986
        l->attrs[0].u.ptr = v1.val.ad;
987
        break;
988
      case EAF_TYPE_UNDEF:
989
        if (v1.type != T_VOID)
990
          runtime( "Setting void attribute to non-void value" );
991
        l->attrs[0].u.data = 0;
992
        break;
993
      default: bug("Unknown type in e,S");
994
      }
995

    
996
      if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
997
        f_rta_cow();
998
        l->next = (*f_rte)->attrs->eattrs;
999
        (*f_rte)->attrs->eattrs = l;
1000
      } else {
1001
        l->next = (*f_tmp_attrs);
1002
        (*f_tmp_attrs) = l;
1003
      }
1004
    }
1005
    break;
1006
  case 'P':
1007
    ACCESS_RTE;
1008
    res.type = T_INT;
1009
    res.val.i = (*f_rte)->pref;
1010
    break;
1011
  case P('P','S'):
1012
    ACCESS_RTE;
1013
    ONEARG;
1014
    if (v1.type != T_INT)
1015
      runtime( "Can't set preference to non-integer" );
1016
    if (v1.val.i > 0xFFFF)
1017
      runtime( "Setting preference value out of bounds" );
1018
    f_rte_cow();
1019
    (*f_rte)->pref = v1.val.i;
1020
    break;
1021
  case 'L':        /* Get length of */
1022
    ONEARG;
1023
    res.type = T_INT;
1024
    switch(v1.type) {
1025
    case T_NET:    res.val.i = net_pxlen(v1.val.net); break;
1026
    case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
1027
    case T_CLIST:  res.val.i = int_set_get_size(v1.val.ad); break;
1028
    case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
1029
    default: runtime( "Prefix, path, clist or eclist expected" );
1030
    }
1031
    break;
1032
  case P('c','p'):        /* Convert prefix to ... */
1033
    ONEARG;
1034
    if (v1.type != T_NET)
1035
      runtime( "Prefix expected" );
1036
    res.type = T_IP;
1037
    res.val.ip = net_prefix(v1.val.net);
1038
    break;
1039
  case P('a','f'):        /* Get first ASN from AS PATH */
1040
    ONEARG;
1041
    if (v1.type != T_PATH)
1042
      runtime( "AS path expected" );
1043

    
1044
    as = 0;
1045
    as_path_get_first(v1.val.ad, &as);
1046
    res.type = T_INT;
1047
    res.val.i = as;
1048
    break;
1049
  case P('a','l'):        /* Get last ASN from AS PATH */
1050
    ONEARG;
1051
    if (v1.type != T_PATH)
1052
      runtime( "AS path expected" );
1053

    
1054
    as = 0;
1055
    as_path_get_last(v1.val.ad, &as);
1056
    res.type = T_INT;
1057
    res.val.i = as;
1058
    break;
1059
  case 'r':
1060
    ONEARG;
1061
    res = v1;
1062
    res.type |= T_RETURN;
1063
    return res;
1064
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
1065
    ONEARG;
1066
    res = interpret(what->a2.p);
1067
    if (res.type == T_RETURN)
1068
      return res;
1069
    res.type &= ~T_RETURN;
1070
    break;
1071
  case P('c','v'):        /* Clear local variables */
1072
    for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
1073
      ((struct f_val *) sym->def)->type = T_VOID;
1074
    break;
1075
  case P('S','W'):
1076
    ONEARG;
1077
    {
1078
      struct f_tree *t = find_tree(what->a2.p, v1);
1079
      if (!t) {
1080
        v1.type = T_VOID;
1081
        t = find_tree(what->a2.p, v1);
1082
        if (!t) {
1083
          debug( "No else statement?\n");
1084
          break;
1085
        }
1086
      }
1087
      /* It is actually possible to have t->data NULL */
1088

    
1089
      res = interpret(t->data);
1090
      if (res.type & T_RETURN)
1091
        return res;
1092
    }
1093
    break;
1094
  case P('i','M'): /* IP.MASK(val) */
1095
    TWOARGS;
1096
    if (v2.type != T_INT)
1097
      runtime( "Integer expected");
1098
    if (v1.type != T_IP)
1099
      runtime( "You can mask only IP addresses" );
1100
    {
1101
      ip_addr mask = ipa_mkmask(v2.val.i);
1102
      res.type = T_IP;
1103
      res.val.ip = ipa_and(mask, v1.val.ip);
1104
    }
1105
    break;
1106

    
1107
  case 'E':        /* Create empty attribute */
1108
    res.type = what->aux;
1109
    res.val.ad = adata_empty(f_pool, 0);
1110
    break;
1111
  case P('A','p'):        /* Path prepend */
1112
    TWOARGS;
1113
    if (v1.type != T_PATH)
1114
      runtime("Can't prepend to non-path");
1115
    if (v2.type != T_INT)
1116
      runtime("Can't prepend non-integer");
1117

    
1118
    res.type = T_PATH;
1119
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
1120
    break;
1121

    
1122
  case P('C','a'):        /* (Extended) Community list add or delete */
1123
    TWOARGS;
1124
    if (v1.type == T_PATH)
1125
    {
1126
      struct f_tree *set = NULL;
1127
      u32 key = 0;
1128
      int pos;
1129

    
1130
      if (v2.type == T_INT)
1131
        key = v2.val.i;
1132
      else if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
1133
        set = v2.val.t;
1134
      else
1135
        runtime("Can't delete non-integer (set)");
1136

    
1137
      switch (what->aux)
1138
      {
1139
      case 'a':        runtime("Can't add to path");
1140
      case 'd':        pos = 0; break;
1141
      case 'f':        pos = 1; break;
1142
      default:        bug("unknown Ca operation");
1143
      }
1144

    
1145
      if (pos && !set)
1146
        runtime("Can't filter integer");
1147

    
1148
      res.type = T_PATH;
1149
      res.val.ad = as_path_filter(f_pool, v1.val.ad, set, key, pos);
1150
    }
1151
    else if (v1.type == T_CLIST)
1152
    {
1153
      /* Community (or cluster) list */
1154
      struct f_val dummy;
1155
      int arg_set = 0;
1156
      uint n = 0;
1157

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

    
1172
      res.type = T_CLIST;
1173
      switch (what->aux)
1174
      {
1175
      case 'a':
1176
        if (arg_set == 1)
1177
          runtime("Can't add set");
1178
        else if (!arg_set)
1179
          res.val.ad = int_set_add(f_pool, v1.val.ad, n);
1180
        else
1181
          res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
1182
        break;
1183

    
1184
      case 'd':
1185
        if (!arg_set)
1186
          res.val.ad = int_set_del(f_pool, v1.val.ad, n);
1187
        else
1188
          res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
1189
        break;
1190

    
1191
      case 'f':
1192
        if (!arg_set)
1193
          runtime("Can't filter pair");
1194
        res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 1);
1195
        break;
1196

    
1197
      default:
1198
        bug("unknown Ca operation");
1199
      }
1200
    }
1201
    else if (v1.type == T_ECLIST)
1202
    {
1203
      /* Extended community list */
1204
      int arg_set = 0;
1205

    
1206
      /* v2.val is either EC or EC-set */
1207
      if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
1208
        arg_set = 1;
1209
      else if (v2.type == T_ECLIST)
1210
        arg_set = 2;
1211
      else if (v2.type != T_EC)
1212
        runtime("Can't add/delete non-pair");
1213

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

    
1226
      case 'd':
1227
        if (!arg_set)
1228
          res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
1229
        else
1230
          res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 0);
1231
        break;
1232

    
1233
      case 'f':
1234
        if (!arg_set)
1235
          runtime("Can't filter ec");
1236
        res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 1);
1237
        break;
1238

    
1239
      default:
1240
        bug("unknown Ca operation");
1241
      }
1242
    }
1243
    else
1244
      runtime("Can't add/delete to non-(e)clist");
1245

    
1246
    break;
1247

    
1248
  case P('R','C'):        /* ROA Check */
1249
    if (what->arg1)
1250
    {
1251
      TWOARGS;
1252
      if ((v1.type != T_NET) || (v2.type != T_INT))
1253
        runtime("Invalid argument to roa_check()");
1254

    
1255
      as = v2.val.i;
1256
    }
1257
    else
1258
    {
1259
      ACCESS_RTE;
1260
      v1.val.net = (*f_rte)->net->n.addr;
1261

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

    
1266
      if (!e || e->type != EAF_TYPE_AS_PATH)
1267
        runtime("Missing AS_PATH attribute");
1268

    
1269
      as_path_get_last(e->u.ptr, &as);
1270
    }
1271

    
1272
    struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
1273
    if (!rtc->table)
1274
      runtime("Missing ROA table");
1275

    
1276
    res.type = T_ENUM_ROA;
1277
    res.val.i = ROA_UNKNOWN;
1278
    // XXXX res.val.i = roa_check_net(rtc->table, &v1.val.net, as);
1279
    break;
1280

    
1281
  default:
1282
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
1283
  }
1284
  if (what->next)
1285
    return interpret(what->next);
1286
  return res;
1287
}
1288

    
1289
#undef ARG
1290
#define ARG(x,y) \
1291
        if (!i_same(f1->y, f2->y)) \
1292
                return 0;
1293

    
1294
#define ONEARG ARG(v1, a1.p)
1295
#define TWOARGS ARG(v1, a1.p) \
1296
                ARG(v2, a2.p)
1297

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

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

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

    
1332
  case '!': ONEARG; break;
1333
  case '~': TWOARGS; break;
1334
  case P('d','e'): ONEARG; break;
1335

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

    
1349
  case 'c':
1350
    switch (f1->aux) {
1351

    
1352
    case T_PREFIX_SET:
1353
      if (!trie_same(f1->a2.p, f2->a2.p))
1354
        return 0;
1355
      break;
1356

    
1357
    case T_SET:
1358
      if (!same_tree(f1->a2.p, f2->a2.p))
1359
        return 0;
1360
      break;
1361

    
1362
    case T_STRING:
1363
      if (strcmp(f1->a2.p, f2->a2.p))
1364
        return 0;
1365
      break;
1366

    
1367
    default:
1368
      A2_SAME;
1369
    }
1370
    break;
1371

    
1372
  case 'C':
1373
    if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
1374
      return 0;
1375
    break;
1376

    
1377
  case 'V':
1378
    if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
1379
      return 0;
1380
    break;
1381
  case 'p': case 'L': ONEARG; break;
1382
  case '?': TWOARGS; break;
1383
  case '0': case 'E': break;
1384
  case P('p',','): ONEARG; A2_SAME; break;
1385
  case 'P':
1386
  case 'a': A2_SAME; break;
1387
  case P('e','a'): A2_SAME; break;
1388
  case P('P','S'):
1389
  case P('a','S'):
1390
  case P('e','S'): ONEARG; A2_SAME; break;
1391

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

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

    
1451
  if (filter == FILTER_REJECT)
1452
    return F_REJECT;
1453

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

    
1457
  f_rte = rte;
1458
  f_old_rta = NULL;
1459
  f_tmp_attrs = tmp_attrs;
1460
  f_pool = tmp_pool;
1461
  f_flags = flags;
1462

    
1463
  LOG_BUFFER_INIT(f_buf);
1464

    
1465
  struct f_val res = interpret(filter->root);
1466

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

    
1483
    rta_free(f_old_rta);
1484
  }
1485

    
1486

    
1487
  if (res.type != T_RETURN) {
1488
    log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
1489
    return F_ERROR;
1490
  }
1491
  DBG( "done (%u)\n", res.val.i );
1492
  return res.val.i;
1493
}
1494

    
1495
/* TODO: perhaps we could integrate f_eval(), f_eval_rte() and f_run() */
1496

    
1497
struct f_val
1498
f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
1499
{
1500
  struct ea_list *tmp_attrs = NULL;
1501

    
1502
  f_rte = rte;
1503
  f_old_rta = NULL;
1504
  f_tmp_attrs = &tmp_attrs;
1505
  f_pool = tmp_pool;
1506
  f_flags = 0;
1507

    
1508
  LOG_BUFFER_INIT(f_buf);
1509

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

    
1513
  /* Hack to include EAF_TEMP attributes to the main list */
1514
  (*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs);
1515

    
1516
  return res;
1517
}
1518

    
1519
struct f_val
1520
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
1521
{
1522
  f_flags = 0;
1523
  f_tmp_attrs = NULL;
1524
  f_rte = NULL;
1525
  f_pool = tmp_pool;
1526

    
1527
  LOG_BUFFER_INIT(f_buf);
1528

    
1529
  return interpret(expr);
1530
}
1531

    
1532
uint
1533
f_eval_int(struct f_inst *expr)
1534
{
1535
  /* Called independently in parse-time to eval expressions */
1536
  struct f_val res = f_eval(expr, cfg_mem);
1537

    
1538
  if (res.type != T_INT)
1539
    cf_error("Integer expression expected");
1540

    
1541
  return res.val.i;
1542
}
1543

    
1544
u32
1545
f_eval_asn(struct f_inst *expr)
1546
{
1547
  /* Called as a part of another interpret call, therefore no log_reset() */
1548
  struct f_val res = interpret(expr);
1549
  return (res.type == T_INT) ? res.val.i : 0;
1550
}
1551

    
1552
/**
1553
 * filter_same - compare two filters
1554
 * @new: first filter to be compared
1555
 * @old: second filter to be compared, notice that this filter is
1556
 * damaged while comparing.
1557
 *
1558
 * Returns 1 in case filters are same, otherwise 0. If there are
1559
 * underlying bugs, it will rather say 0 on same filters than say
1560
 * 1 on different.
1561
 */
1562
int
1563
filter_same(struct filter *new, struct filter *old)
1564
{
1565
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
1566
    return 1;
1567
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
1568
      new == FILTER_ACCEPT || new == FILTER_REJECT)
1569
    return 0;
1570
  return i_same(new->root, old->root);
1571
}