Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 26c09e1d

History | View | Annotate | Download (19.2 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 filters language in filter/
14
 * directory. filter/config.Y filter grammar, and basically translates
15
 * source from user into tree of &f_inst structures. These trees are
16
 * later interpreted using code in filter/filter.c. Filters internally
17
 * work with values/variables in struct f_val, which contains type of
18
 * value and value.
19
 *
20
 * Filter consists of tree of &f_inst structures, one structure per
21
 * "instruction". Each &f_inst contains code, aux value which is
22
 * usually type of data this instruction operates on, and two generic
23
 * arguments (a1, a2). Some instructinos contain pointer(s) to other
24
 * instructions in their (a1, a2) fields.
25
 *
26
 * Filters use structure &f_val for its variables. Each &f_val
27
 * contains type and value. Types are constants prefixed with %T_. Few
28
 * of types are special; %T_RETURN can be or-ed with type to indicate
29
 * that return from function/from whole filter should be
30
 * forced. Important thing about &f_val s is that they may be copied
31
 * with simple =. That's fine for all currently defined types: strings
32
 * are read-only (and therefore okay), paths are copied for each
33
 * operation (okay too).  */
34

    
35
#undef LOCAL_DEBUG
36

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

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

    
52
#define CMP_ERROR 999
53

    
54
struct adata *
55
adata_empty(struct linpool *pool)
56
{
57
  struct adata *res = lp_alloc(pool, sizeof(struct adata));
58
  res->length = 0;
59
  return res;
60
}
61

    
62
static int
63
pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
64
{
65
  while (1) {
66
    if ((!m1) || (!m2))
67
      return !((!m1) && (!m2));
68
    m1 = m1->next;
69
    m2 = m2->next;
70
  }
71
}
72

    
73
/* Compare two values, returns -1, 0, 1 compared, ERROR 999 */
74
int
75
val_compare(struct f_val v1, struct f_val v2)
76
{
77
  if ((v1.type == T_VOID) && (v2.type == T_VOID))
78
    return 0;
79
  if (v1.type == T_VOID)        /* Hack for else */
80
    return -1;
81
  if (v2.type == T_VOID)
82
    return 1;
83

    
84
  if (v1.type != v2.type) {
85
    debug( "Types do not match in val_compare\n" );
86
    return CMP_ERROR;
87
  }
88
  switch (v1.type) {
89
  case T_ENUM:
90
  case T_INT: 
91
  case T_PAIR:
92
    if (v1.val.i == v2.val.i) return 0;
93
    if (v1.val.i < v2.val.i) return -1;
94
    return 1;
95
  case T_IP:
96
  case T_PREFIX:
97
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
98
  case T_PATH_MASK:
99
    return pm_path_compare(v1.val.path_mask, v2.val.path_mask);
100
  default:
101
    debug( "Compare of unkown entities: %x\n", v1.type );
102
    return CMP_ERROR;
103
  }
104
}
105

    
106
int
107
val_simple_in_range(struct f_val v1, struct f_val v2)
108
{
109
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
110
    return as_path_match(v1.val.ad, v2.val.path_mask);
111
  if ((v1.type == T_PAIR) && (v2.type == T_CLIST))
112
    return int_set_contains(v2.val.ad, v1.val.i);
113

    
114
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
115
    return !(ipa_compare(ipa_and(v2.val.px.ip, ipa_mkmask(v2.val.px.len)), ipa_and(v1.val.px.ip, ipa_mkmask(v2.val.px.len))));
116

    
117
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) {
118
    ip_addr mask;
119
    if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE))
120
      return CMP_ERROR;
121
    mask = ipa_mkmask( v2.val.px.len & LEN_MASK );
122
    if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask)))
123
      return 0;
124

    
125
    if ((v2.val.px.len & LEN_MINUS) && (v1.val.px.len <= (v2.val.px.len & LEN_MASK)))
126
      return 0;
127
    if ((v2.val.px.len & LEN_PLUS) && (v1.val.px.len < (v2.val.px.len & LEN_MASK)))
128
      return 0;
129
    if ((v2.val.px.len & LEN_RANGE) && ((v1.val.px.len < (0xff & (v2.val.px.len >> 16)))
130
                                        || (v1.val.px.len > (0xff & (v2.val.px.len >> 8)))))
131
      return 0;
132
    return 1;    
133
  }
134
  return CMP_ERROR;
135
}
136

    
137
int
138
val_in_range(struct f_val v1, struct f_val v2)
139
{
140
  int res;
141

    
142
  res = val_simple_in_range(v1, v2);
143

    
144
  if (res != CMP_ERROR)
145
    return res;
146

    
147
  if (((v1.type == T_INT) || ((v1.type == T_IP) || (v1.type == T_PREFIX)) && (v2.type == T_SET))) {
148
    struct f_tree *n;
149
    n = find_tree(v2.val.t, v1);
150
    if (!n)
151
      return 0;
152
    return !! (val_simple_in_range(v1, n->from));        /* We turn CMP_ERROR into compared ok, and that's fine */
153
  }
154
  return CMP_ERROR;
155
}
156

    
157
static void
158
tree_print(struct f_tree *t)
159
{
160
  if (!t) {
161
    debug( "() " );
162
    return;
163
  }
164
  debug( "[ " );
165
  tree_print( t->left );
166
  debug( ", " ); val_print( t->from ); debug( ".." ); val_print( t->to ); debug( ", " );
167
  tree_print( t->right );
168
  debug( "] " );
169
}
170

    
171
void
172
val_print(struct f_val v)
173
{
174
  char buf[2048];
175
  char buf2[1024];
176
#define PRINTF(a...) bsnprintf( buf, 2040, a )
177
  buf[0] = 0;
178
  switch (v.type) {
179
  case T_VOID: PRINTF( "(void)" ); break;
180
  case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
181
  case T_INT: PRINTF( "%d ", v.val.i ); break;
182
  case T_STRING: PRINTF( "%s", v.val.s ); break;
183
  case T_IP: PRINTF( "%I", v.val.px.ip ); break;
184
  case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
185
  case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
186
  case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
187
  case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
188
  case T_PATH: as_path_format(v.val.ad, buf2, 1020); PRINTF( "(path %s)", buf2 ); break;
189
  case T_CLIST: int_set_format(v.val.ad, buf2, 1020); PRINTF( "(clist %s)", buf2 ); break;
190
  case T_PATH_MASK: debug( "(pathmask " ); { struct f_path_mask *p = v.val.path_mask; while (p) { debug("%d ", p->val); p=p->next; } debug(")" ); } break;
191
  default: PRINTF( "[unknown type %x]", v.type );
192
#undef PRINTF
193
  }
194
  debug( buf );
195
}
196

    
197
static struct rte **f_rte, *f_rte_old;
198
static struct linpool *f_pool;
199
static struct ea_list **f_tmp_attrs;
200
static int f_flags;
201
static rta *f_rta_copy;
202

    
203
void
204
rta_cow(void)
205
{
206
  if (!f_rta_copy) {
207
    f_rta_copy = lp_alloc(f_pool, sizeof(rta));
208
    memcpy(f_rta_copy, (*f_rte)->attrs, sizeof(rta));
209
    f_rta_copy->aflags = 0;
210
    *f_rte = rte_cow(*f_rte);
211
    (*f_rte)->attrs = f_rta_copy;
212
  }
213
}
214

    
215
#define runtime(x) do { \
216
    log( L_ERR "filters, line %d: %s", what->lineno, x); \
217
    res.type = T_RETURN; \
218
    res.val.i = F_ERROR; \
219
    return res; \
220
  } while(0)
221

    
222
#define ARG(x,y) \
223
        x = interpret(what->y); \
224
        if (x.type & T_RETURN) \
225
                return x;
226

    
227
#define ONEARG ARG(v1, a1.p)
228
#define TWOARGS ARG(v1, a1.p) \
229
                ARG(v2, a2.p)
230
#define TWOARGS_C TWOARGS \
231
                  if (v1.type != v2.type) \
232
                    runtime( "Can not operate with values of incompatible types" );
233

    
234
static struct f_val
235
interpret(struct f_inst *what)
236
{
237
  struct symbol *sym;
238
  struct f_val v1, v2, res;
239
  int i,j,k;
240

    
241
  res.type = T_VOID;
242
  if (!what)
243
    return res;
244

    
245
  switch(what->code) {
246
  case ',':
247
    TWOARGS;
248
    break;
249

    
250
/* Binary operators */
251
  case '+':
252
    TWOARGS_C;
253
    switch (res.type = v1.type) {
254
    case T_VOID: runtime( "Can not operate with values of type void" );
255
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
256
    default: runtime( "Usage of unknown type" );
257
    }
258
    break;
259
  case '-':
260
    TWOARGS_C;
261
    switch (res.type = v1.type) {
262
    case T_VOID: runtime( "Can not operate with values of type void" );
263
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
264
    default: runtime( "Usage of unknown type" );
265
    }
266
    break;
267
  case '*':
268
    TWOARGS_C;
269
    switch (res.type = v1.type) {
270
    case T_VOID: runtime( "Can not operate with values of type void" );
271
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
272
    default: runtime( "Usage of unknown type" );
273
    }
274
    break;
275
  case '/':
276
    TWOARGS_C;
277
    switch (res.type = v1.type) {
278
    case T_VOID: runtime( "Can not operate with values of type void" );
279
    case T_INT: res.val.i = v1.val.i / v2.val.i; break;
280
    case T_IP: if (v2.type != T_INT)
281
                 runtime( "Operator / is <ip>/<int>" );
282
               break;
283
    default: runtime( "Usage of unknown type" );
284
    }
285
    break;
286

    
287
/* Relational operators */
288

    
289
#define COMPARE(x) \
290
    TWOARGS_C; \
291
    res.type = T_BOOL; \
292
    i = val_compare(v1, v2); \
293
    if (i==CMP_ERROR) \
294
      runtime( "Error in comparation" ); \
295
    res.val.i = (x); \
296
    break;
297

    
298
  case P('!','='): COMPARE(i!=0);
299
  case P('=','='): COMPARE(i==0);
300
  case '<': COMPARE(i==-1);
301
  case P('<','='): COMPARE(i!=1);
302

    
303
  case '!':
304
    ONEARG;
305
    if (v1.type != T_BOOL)
306
      runtime( "not applied to non-boolean" );
307
    res = v1;
308
    res.val.i = !res.val.i;
309
    break;
310

    
311
  case '~':
312
    TWOARGS;
313
    res.type = T_BOOL;
314
    res.val.i = val_in_range(v1, v2);
315
    if (res.val.i == CMP_ERROR)
316
      runtime( "~ applied on unknown type pair" );
317
    break;
318
  case P('d','e'):
319
    ONEARG;
320
    res.type = T_BOOL;
321
    res.val.i = (v1.type != T_VOID);
322
    break;
323

    
324
  /* Set to indirect value, a1 = variable, a2 = value */
325
  case 's':
326
    ARG(v2, a2.p);
327
    sym = what->a1.p;
328
    switch (res.type = v2.type) {
329
    case T_VOID: runtime( "Can not assign void values" );
330
    case T_ENUM:
331
    case T_INT: 
332
    case T_IP: 
333
    case T_PREFIX: 
334
    case T_PAIR: 
335
    case T_PATH:
336
    case T_CLIST:
337
    case T_PATH_MASK:
338
      if (sym->class != (SYM_VARIABLE | v2.type))
339
        runtime( "Variable of bad type" );
340
      * (struct f_val *) sym->aux2 = v2; 
341
      break;
342
    default:
343
      bug( "Set to invalid type" );
344
    }
345
    break;
346

    
347
  case 'c':        /* integer (or simple type) constant */
348
    res.type = what->aux;
349
    res.val.i = what->a2.i;
350
    break;
351
  case 'C':
352
    res = * ((struct f_val *) what->a1.p);
353
    break;
354
  case 'p':
355
    ONEARG;
356
    val_print(v1);
357
    break;
358
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
359
    ONEARG;
360
    if (v1.type != T_BOOL)
361
      runtime( "If requires bool expression" );
362
    if (v1.val.i) {
363
      ARG(res,a2.p);
364
      res.val.i = 0;
365
    } else res.val.i = 1;
366
    res.type = T_BOOL;
367
    break;
368
  case '0':
369
    debug( "No operation\n" );
370
    break;
371
  case P('p',','):
372
    ONEARG;
373
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
374
      debug( "\n" );
375

    
376
    switch (what->a2.i) {
377
    case F_QUITBIRD:
378
      die( "Filter asked me to die" );
379
    case F_ACCEPT:
380
      /* Should take care about turning ACCEPT into MODIFY */
381
    case F_ERROR:
382
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
383
      res.type = T_RETURN;
384
      res.val.i = what->a2.i;
385
      return res;        /* We have to return now, no more processing. */
386
    case F_NONL:
387
    case F_NOP:
388
      break;
389
    default:
390
      bug( "unknown return type: can not happen");
391
    }
392
    break;
393
  case 'a':        /* rta access */
394
    {
395
      struct rta *rta = (*f_rte)->attrs;
396
      res.type = what->aux;
397
      switch(res.type) {
398
      case T_IP:
399
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
400
        break;
401
      case T_ENUM:
402
        res.val.i = * ((char *) rta + what->a2.i);
403
        break;
404
      case T_PREFIX:        /* Warning: this works only for prefix of network */
405
        {
406
          res.val.px.ip = (*f_rte)->net->n.prefix;
407
          res.val.px.len = (*f_rte)->net->n.pxlen;
408
          break;
409
        }
410
      default:
411
        bug( "Invalid type for rta access (%x)", res.type );
412
      }
413
    }
414
    break;
415
  case P('e','a'):        /* Access to extended attributes */
416
    {
417
      eattr *e = NULL;
418
      if (!(f_flags & FF_FORCE_TMPATTR))
419
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
420
      if (!e) 
421
        e = ea_find( (*f_tmp_attrs), what->a2.i );
422
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
423
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
424
      
425
      switch (what->aux & EAF_TYPE_MASK) {
426
      case EAF_TYPE_INT:
427
        if (!e) {
428
          res.type = T_VOID;
429
          break;
430
        }
431
        res.type = T_INT;
432
        res.val.i = e->u.data;
433
        break;
434
      case EAF_TYPE_AS_PATH:
435
        if (!e) {
436
          res.type = T_VOID;
437
          break;
438
        }
439
        res.type = T_PATH;
440
        res.val.ad = e->u.ptr;
441
        break;
442
      case EAF_TYPE_INT_SET:
443
        if (!e) {
444
          res.type = T_CLIST;
445
          res.val.ad = adata_empty(f_pool);
446
          break;
447
        }
448
        res.type = T_CLIST;
449
        res.val.ad = e->u.ptr;
450
        break;
451
      default:
452
        bug("Unknown type in e,a");
453
      }
454
    }
455
    break;
456
  case P('e','S'):
457
    ONEARG;
458
    {
459
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
460

    
461
      l->next = NULL;
462
      l->flags = EALF_SORTED;
463
      l->count = 1;
464
      l->attrs[0].id = what->a2.i;
465
      l->attrs[0].flags = 0;
466
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
467
      switch (what->aux & EAF_TYPE_MASK) {
468
      case EAF_TYPE_INT:
469
        if (v1.type != T_INT)
470
          runtime( "Setting int attribute to non-int value" );
471
        l->attrs[0].u.data = v1.val.i;
472
        break;
473
      case EAF_TYPE_AS_PATH:
474
        if (v1.type != T_PATH)
475
          runtime( "Setting path attribute to non-path value" );
476
        l->attrs[0].u.ptr = v1.val.ad;
477
        break;
478
      case EAF_TYPE_INT_SET:
479
        if (v1.type != T_CLIST)
480
          runtime( "Setting int set  attribute to non-clist value" );
481
        l->attrs[0].u.ptr = v1.val.ad;
482
        break;
483
      case EAF_TYPE_UNDEF:
484
        if (v1.type != T_VOID)
485
          runtime( "Setting void attribute to non-void value" );
486
        l->attrs[0].u.data = 0;
487
        break;
488
      default: bug("Unknown type in e,S");
489
      }
490

    
491
      if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
492
        rta_cow();
493
        l->next = f_rta_copy->eattrs;
494
        f_rta_copy->eattrs = l;
495
      } else {
496
        l->next = (*f_tmp_attrs);
497
        (*f_tmp_attrs) = l;
498
      }
499
    }
500
    break;
501

    
502
  case 'L':        /* Get length of */
503
    ONEARG;
504
    res.type = T_INT;
505
    switch(v1.type) {
506
    case T_PREFIX: res.val.i = v1.val.px.len; break;
507
    case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
508
    default: bug( "Length of what?" );
509
    }
510
    break;
511
  case P('c','p'):        /* Convert prefix to ... */
512
    ONEARG;
513
    if (v1.type != T_PREFIX)
514
      runtime( "Can not convert non-prefix this way" );
515
    res.type = what->aux;
516
    switch(res.type) {
517
      /*    case T_INT:        res.val.i = v1.val.px.len; break; Not needed any more */
518
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
519
    default: bug( "Unknown prefix to conversion" );
520
    }
521
    break;
522
  case 'r':
523
    ONEARG;
524
    res = v1;
525
    res.type |= T_RETURN;
526
    break;
527
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
528
    ONEARG;
529
    res = interpret(what->a2.p);
530
    if (res.type == T_RETURN)
531
      return res;
532
    res.type &= ~T_RETURN;    
533
    break;
534
  case P('S','W'):
535
    ONEARG;
536
    {
537
      struct f_tree *t = find_tree(what->a2.p, v1);
538
      if (!t) {
539
        v1.type = T_VOID;
540
        t = find_tree(what->a2.p, v1);
541
        if (!t) {
542
          debug( "No else statement?\n");
543
          break;
544
        }
545
      }        
546
      if (!t->data)
547
        bug( "Impossible: no code associated!" );
548
      return interpret(t->data);
549
    }
550
    break;
551
  case P('i','M'): /* IP.MASK(val) */
552
    TWOARGS;
553
    if (v2.type != T_INT)
554
      runtime( "Can not use this type for mask.");
555
    if (v1.type != T_IP)
556
      runtime( "You can mask only IP addresses." );
557
    {
558
      ip_addr mask = ipa_mkmask(v2.val.i);
559
      res.type = T_IP;
560
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
561
    }
562
    break;
563

    
564
  case 'E':        /* Create empty attribute */
565
    res.type = what->aux;
566
    res.val.ad = adata_empty(f_pool);
567
    break;
568
  case P('A','p'):        /* Path prepend */
569
    TWOARGS;
570
    if (v1.type != T_PATH)
571
      runtime("Can't prepend to non-path");
572
    if (v2.type != T_INT)
573
      runtime("Can't prepend non-integer");
574

    
575
    res.type = T_PATH;
576
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
577
    break;
578

    
579
  case P('C','a'):        /* Community list add or delete */
580
    TWOARGS;
581
    if (v1.type != T_CLIST)
582
      runtime("Can't add/delete to non-clist");
583
    if (v2.type != T_PAIR)
584
      runtime("Can't add/delete non-pair");
585

    
586
    res.type = T_CLIST;
587
    switch (what->aux) {
588
    case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, v2.val.i); break;
589
    case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, v2.val.i); break;
590
    default: bug("unknown Ca operation");
591
    }
592
    break;
593

    
594
  default:
595
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
596
  }
597
  if (what->next)
598
    return interpret(what->next);
599
  return res;
600
}
601

    
602
#undef ARG
603
#define ARG(x,y) \
604
        if (!i_same(f1->y, f2->y)) \
605
                return 0;
606

    
607
#define ONEARG ARG(v1, a1.p)
608
#define TWOARGS ARG(v1, a1.p) \
609
                ARG(v2, a2.p)
610

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

    
613
int
614
i_same(struct f_inst *f1, struct f_inst *f2)
615
{
616
  if ((!!f1) != (!!f2))
617
    return 0;
618
  if (!f1)
619
    return 1;
620
  if (f1->aux != f2->aux)
621
    return 0;
622
  if (f1->code != f2->code)
623
    return 0;
624
  if (f1 == f2)                /* It looks strange, but it is possible with call rewriting trickery */
625
    return 1;
626

    
627
  switch(f1->code) {
628
  case ',': /* fall through */
629
  case '+':
630
  case '-':
631
  case '*':
632
  case '/':
633
  case P('!','='):
634
  case P('=','='):
635
  case '<':
636
  case P('<','='): TWOARGS; break;
637

    
638
  case '!': ONEARG; break;
639
  case '~': TWOARGS; break;
640
  case P('d','e'): ONEARG; break;
641

    
642
  case 's':
643
    ARG(v2, a2.p);
644
    {
645
      struct symbol *s1, *s2;
646
      s1 = f1->a1.p;
647
      s2 = f2->a1.p;
648
      if (strcmp(s1->name, s2->name))
649
        return 0;
650
      if (s1->class != s2->class)
651
        return 0;
652
    }
653
    break;
654

    
655
  case 'c': A2_SAME; break;
656
  case 'C': 
657
    if (val_compare(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
658
      return 0;
659
    break;
660
  case 'p': case 'L': ONEARG; break;
661
  case '?': TWOARGS; break;
662
  case '0': case 'E': break;
663
  case P('p',','): ONEARG; A2_SAME; break;
664
  case 'a': A2_SAME; break;
665
  case P('e','a'): A2_SAME; break;
666
  case P('e','S'): ONEARG; A2_SAME; break;
667

    
668
  case 'r': ONEARG; break;
669
  case P('c','p'): ONEARG; break;
670
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
671
             ONEARG; 
672
             if (!i_same(f1->a2.p, f2->a2.p))
673
               return 0; 
674
             f2->a2.p = f1->a2.p;
675
             break;
676
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
677
  case P('i','M'): TWOARGS; break;
678
  case P('A','p'): TWOARGS; break;
679
  case P('C','a'): TWOARGS; break;
680
  default:
681
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
682
  }
683
  return i_same(f1->next, f2->next);
684
}
685

    
686
/**
687
 * f_run - external entry point to filters
688
 * @filter: pointer to filter to run
689
 * @rte: pointer to pointer to rte being filtered. When route is modified, this is changed with rte_cow.
690
 * @tmp_pool: all filter allocations go from this pool
691
 */
692
int
693
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
694
{
695
  struct f_inst *inst;
696
  struct f_val res;
697
  DBG( "Running filter `%s'...", filter->name );
698

    
699
  f_flags = flags;
700
  f_tmp_attrs = tmp_attrs;
701
  f_rte = rte;
702
  f_rte_old = *rte;
703
  f_rta_copy = NULL;
704
  f_pool = tmp_pool;
705
  inst = filter->root;
706
  res = interpret(inst);
707
  if (res.type != T_RETURN)
708
    return F_ERROR;
709
  DBG( "done (%d)\n", res.val.i );
710
  return res.val.i;
711
}
712

    
713
int
714
f_eval_int(struct f_inst *expr)
715
{
716
  struct f_val res;
717

    
718
  f_flags = 0;
719
  f_tmp_attrs = NULL;
720
  f_rte = NULL;
721
  f_rte_old = NULL;
722
  f_rta_copy = NULL;
723
  f_pool = cfg_mem;
724
  res = interpret(expr);
725
  if (res.type != T_INT)
726
    cf_error("Integer expression expected");
727
  return res.val.i;
728
}
729

    
730
/**
731
 * filter_same - compare two filters
732
 * @new: first filter to be compared
733
 * @old: second filter to be compared, notice that this filter is
734
 * damaged while comparing.
735
 *
736
 * Returns 1 in case filters are same, otherwise 0. If there are
737
 * underlying bugs, it will rather say 0 on same filters than say
738
 * 1 on different.
739
 */
740
int
741
filter_same(struct filter *new, struct filter *old)
742
{
743
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
744
    return 1;
745
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
746
      new == FILTER_ACCEPT || new == FILTER_REJECT)
747
    return 0;
748
  return i_same(new->root, old->root);
749
}