Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 9f0d45d6

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

    
29
#undef LOCAL_DEBUG
30

    
31
#include "nest/bird.h"
32
#include "lib/lists.h"
33
#include "lib/resource.h"
34
#include "lib/socket.h"
35
#include "lib/string.h"
36
#include "lib/unaligned.h"
37
#include "nest/route.h"
38
#include "nest/protocol.h"
39
#include "nest/iface.h"
40
#include "nest/attrs.h"
41
#include "conf/conf.h"
42
#include "filter/filter.h"
43

    
44
#define P(a,b) ((a<<8) | b)
45

    
46
#define CMP_ERROR 999
47

    
48
static int
49
pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
50
{
51
  while (1) {
52
    if ((!m1) || (!m2))
53
      return !((!m1) && (!m2));
54
    m1 = m1->next;
55
    m2 = m2->next;
56
  }
57
}
58

    
59
/* Compare two values, returns -1, 0, 1 compared, ERROR 999 */
60
int
61
val_compare(struct f_val v1, struct f_val v2)
62
{
63
  if ((v1.type == T_VOID) && (v2.type == T_VOID))
64
    return 0;
65
  if (v1.type == T_VOID)        /* Hack for else */
66
    return -1;
67
  if (v2.type == T_VOID)
68
    return 1;
69

    
70
  if (v1.type != v2.type) {
71
    debug( "Types do not match in val_compare\n" );
72
    return CMP_ERROR;
73
  }
74
  switch (v1.type) {
75
  case T_ENUM:
76
  case T_INT: 
77
  case T_PAIR:
78
    if (v1.val.i == v2.val.i) return 0;
79
    if (v1.val.i < v2.val.i) return -1;
80
    return 1;
81
  case T_IP:
82
  case T_PREFIX:
83
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
84
  case T_PATH_MASK:
85
    return pm_path_compare(v1.val.path_mask, v2.val.path_mask);
86
  default:
87
    debug( "Compare of unkown entities: %x\n", v1.type );
88
    return CMP_ERROR;
89
  }
90
}
91

    
92
int
93
val_simple_in_range(struct f_val v1, struct f_val v2)
94
{
95
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
96
    return as_path_match(v1.val.ad, v2.val.path_mask);
97
  if ((v1.type == T_PAIR) && (v2.type == T_CLIST))
98
    return int_set_contains(v2.val.ad, v1.val.i);
99

    
100
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
101
    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))));
102

    
103
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) {
104
    ip_addr mask;
105
    if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE))
106
      return CMP_ERROR;
107
    mask = ipa_mkmask( v2.val.px.len & LEN_MASK );
108
    if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask)))
109
      return 0;
110

    
111
    if ((v2.val.px.len & LEN_MINUS) && (v1.val.px.len <= (v2.val.px.len & LEN_MASK)))
112
      return 0;
113
    if ((v2.val.px.len & LEN_PLUS) && (v1.val.px.len < (v2.val.px.len & LEN_MASK)))
114
      return 0;
115
    if ((v2.val.px.len & LEN_RANGE) && ((v1.val.px.len < (0xff & (v2.val.px.len >> 16)))
116
                                        || (v1.val.px.len > (0xff & (v2.val.px.len >> 8)))))
117
      return 0;
118
    return 1;    
119
  }
120
  return CMP_ERROR;
121
}
122

    
123
int
124
val_in_range(struct f_val v1, struct f_val v2)
125
{
126
  int res;
127

    
128
  res = val_simple_in_range(v1, v2);
129

    
130
  if (res != CMP_ERROR)
131
    return res;
132

    
133
  if (((v1.type == T_INT) || ((v1.type == T_IP) || (v1.type == T_PREFIX)) && (v2.type == T_SET))) {
134
    struct f_tree *n;
135
    n = find_tree(v2.val.t, v1);
136
    if (!n)
137
      return 0;
138
    return !! (val_simple_in_range(v1, n->from));        /* We turn CMP_ERROR into compared ok, and that's fine */
139
  }
140
  return CMP_ERROR;
141
}
142

    
143
static void
144
tree_print(struct f_tree *t)
145
{
146
  if (!t) {
147
    debug( "() " );
148
    return;
149
  }
150
  debug( "[ " );
151
  tree_print( t->left );
152
  debug( ", " ); val_print( t->from ); debug( ".." ); val_print( t->to ); debug( ", " );
153
  tree_print( t->right );
154
  debug( "] " );
155
}
156

    
157
void
158
val_print(struct f_val v)
159
{
160
  char buf[2048];
161
  char buf2[1024];
162
#define PRINTF(a...) bsnprintf( buf, 2040, a )
163
  buf[0] = 0;
164
  switch (v.type) {
165
  case T_VOID: PRINTF( "(void)" ); break;
166
  case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
167
  case T_INT: PRINTF( "%d ", v.val.i ); break;
168
  case T_STRING: PRINTF( "%s", v.val.s ); break;
169
  case T_IP: PRINTF( "%I", v.val.px.ip ); break;
170
  case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
171
  case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
172
  case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
173
  case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
174
  case T_PATH: as_path_format(v.val.ad, buf2, 1020); PRINTF( "(path %s)", buf2 ); break;
175
  case T_CLIST: int_set_format(v.val.ad, buf2, 1020); PRINTF( "(clist %s)", buf2 ); break;
176
  case T_PATH_MASK: debug( "(pathmask " ); { struct f_path_mask *p = v.val.s; while (p) { debug("%d ", p->val); p=p->next; } debug(")" ); } break;
177
  default: PRINTF( "[unknown type %x]", v.type );
178
#undef PRINTF
179
  }
180
  debug( buf );
181
}
182

    
183
static struct rte **f_rte, *f_rte_old;
184
static struct linpool *f_pool;
185
static struct ea_list **f_tmp_attrs;
186
static int f_flags;
187
static rta *f_rta_copy;
188

    
189
#define runtime(x) do { \
190
    log( L_ERR "filters, line %d: %s", what->lineno, x); \
191
    res.type = T_RETURN; \
192
    res.val.i = F_ERROR; \
193
    return res; \
194
  } while(0)
195

    
196
#define ARG(x,y) \
197
        x = interpret(what->y); \
198
        if (x.type & T_RETURN) \
199
                return x;
200

    
201
#define ONEARG ARG(v1, a1.p)
202
#define TWOARGS ARG(v1, a1.p) \
203
                ARG(v2, a2.p)
204
#define TWOARGS_C TWOARGS \
205
                  if (v1.type != v2.type) \
206
                    runtime( "Can not operate with values of incompatible types" );
207

    
208
static struct f_val
209
interpret(struct f_inst *what)
210
{
211
  struct symbol *sym;
212
  struct f_val v1, v2, res;
213
  int i,j,k;
214

    
215
  res.type = T_VOID;
216
  if (!what)
217
    return res;
218

    
219
  switch(what->code) {
220
  case ',':
221
    TWOARGS;
222
    break;
223

    
224
/* Binary operators */
225
  case '+':
226
    TWOARGS_C;
227
    switch (res.type = v1.type) {
228
    case T_VOID: runtime( "Can not operate with values of type void" );
229
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
230
    default: runtime( "Usage of unknown type" );
231
    }
232
    break;
233
  case '-':
234
    TWOARGS_C;
235
    switch (res.type = v1.type) {
236
    case T_VOID: runtime( "Can not operate with values of type void" );
237
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
238
    default: runtime( "Usage of unknown type" );
239
    }
240
    break;
241
  case '*':
242
    TWOARGS_C;
243
    switch (res.type = v1.type) {
244
    case T_VOID: runtime( "Can not operate with values of type void" );
245
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
246
    default: runtime( "Usage of unknown type" );
247
    }
248
    break;
249
  case '/':
250
    TWOARGS_C;
251
    switch (res.type = v1.type) {
252
    case T_VOID: runtime( "Can not operate with values of type void" );
253
    case T_INT: res.val.i = v1.val.i / v2.val.i; break;
254
    case T_IP: if (v2.type != T_INT)
255
                 runtime( "Operator / is <ip>/<int>" );
256
               break;
257
    default: runtime( "Usage of unknown type" );
258
    }
259
    break;
260

    
261
/* Relational operators */
262

    
263
#define COMPARE(x) \
264
    TWOARGS_C; \
265
    res.type = T_BOOL; \
266
    i = val_compare(v1, v2); \
267
    if (i==CMP_ERROR) \
268
      runtime( "Error in comparation" ); \
269
    res.val.i = (x); \
270
    break;
271

    
272
  case P('!','='): COMPARE(i!=0);
273
  case P('=','='): COMPARE(i==0);
274
  case '<': COMPARE(i==-1);
275
  case P('<','='): COMPARE(i!=1);
276

    
277
  case '!':
278
    ONEARG;
279
    if (v1.type != T_BOOL)
280
      runtime( "not applied to non-boolean" );
281
    res = v1;
282
    res.val.i = !res.val.i;
283
    break;
284

    
285
  case '~':
286
    TWOARGS;
287
    res.type = T_BOOL;
288
    res.val.i = val_in_range(v1, v2);
289
    if (res.val.i == CMP_ERROR)
290
      runtime( "~ applied on unknown type pair" );
291
    break;
292
  case P('d','e'):
293
    ONEARG;
294
    res.type = T_BOOL;
295
    res.val.i = (v1.type != T_VOID);
296
    break;
297

    
298
  /* Set to indirect value, a1 = variable, a2 = value */
299
  case 's':
300
    ARG(v2, a2.p);
301
    sym = what->a1.p;
302
    switch (res.type = v2.type) {
303
    case T_VOID: runtime( "Can not assign void values" );
304
    case T_ENUM:
305
    case T_INT: 
306
    case T_IP: 
307
    case T_PREFIX: 
308
    case T_PAIR: 
309
    case T_PATH:
310
    case T_CLIST:
311
    case T_PATH_MASK:
312
      if (sym->class != (SYM_VARIABLE | v2.type))
313
        runtime( "Variable of bad type" );
314
      * (struct f_val *) sym->aux2 = v2; 
315
      break;
316
    default:
317
      bug( "Set to invalid type" );
318
    }
319
    break;
320

    
321
  case 'c':        /* integer (or simple type) constant */
322
    res.type = what->aux;
323
    res.val.i = what->a2.i;
324
    break;
325
  case 'C':
326
    res = * ((struct f_val *) what->a1.p);
327
    break;
328
  case 'p':
329
    ONEARG;
330
    val_print(v1);
331
    break;
332
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
333
    ONEARG;
334
    if (v1.type != T_BOOL)
335
      runtime( "If requires bool expression" );
336
    if (v1.val.i) {
337
      ARG(res,a2.p);
338
      res.val.i = 0;
339
    } else res.val.i = 1;
340
    res.type = T_BOOL;
341
    break;
342
  case '0':
343
    debug( "No operation\n" );
344
    break;
345
  case P('p',','):
346
    ONEARG;
347
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
348
      debug( "\n" );
349

    
350
    switch (what->a2.i) {
351
    case F_QUITBIRD:
352
      die( "Filter asked me to die" );
353
    case F_ACCEPT:
354
      /* Should take care about turning ACCEPT into MODIFY */
355
    case F_ERROR:
356
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
357
      res.type = T_RETURN;
358
      res.val.i = what->a2.i;
359
      return res;        /* We have to return now, no more processing. */
360
    case F_NONL:
361
    case F_NOP:
362
      break;
363
    default:
364
      bug( "unknown return type: can not happen");
365
    }
366
    break;
367
  case 'a':        /* rta access */
368
    {
369
      struct rta *rta = (*f_rte)->attrs;
370
      res.type = what->aux;
371
      switch(res.type) {
372
      case T_IP:
373
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
374
        break;
375
      case T_ENUM:
376
        res.val.i = * ((char *) rta + what->a2.i);
377
        break;
378
      case T_PREFIX:        /* Warning: this works only for prefix of network */
379
        {
380
          res.val.px.ip = (*f_rte)->net->n.prefix;
381
          res.val.px.len = (*f_rte)->net->n.pxlen;
382
          break;
383
        }
384
      default:
385
        bug( "Invalid type for rta access (%x)", res.type );
386
      }
387
    }
388
    break;
389
  case P('e','a'):        /* Access to extended attributes */
390
    {
391
      eattr *e = NULL;
392
      if (!(f_flags & FF_FORCE_TMPATTR))
393
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
394
      if (!e) 
395
        e = ea_find( (*f_tmp_attrs), what->a2.i );
396
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
397
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
398
      
399
      if (!e) {
400
        res.type = T_VOID;
401
        break;
402
      }
403
      switch (what->aux & EAF_TYPE_MASK) {
404
      case EAF_TYPE_INT:
405
        res.type = T_INT;
406
        res.val.i = e->u.data;
407
        break;
408
      case EAF_TYPE_AS_PATH:
409
        res.type = T_PATH;
410
        res.val.ad = e->u.ptr;
411
        break;
412
      case EAF_TYPE_INT_SET:
413
        res.type = T_CLIST;
414
        res.val.ad = e->u.ptr;
415
        break;
416
      default:
417
        bug("Unknown type in e,a\n");
418
      }
419
    }
420
    break;
421
  case P('e','S'):
422
    ONEARG;
423
    {
424
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
425

    
426
      l->next = NULL;
427
      l->flags = EALF_SORTED;
428
      l->count = 1;
429
      l->attrs[0].id = what->a2.i;
430
      l->attrs[0].flags = 0;
431
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
432
      switch (what->aux & EAF_TYPE_MASK) {
433
      case EAF_TYPE_INT:
434
        if (v1.type != T_INT)
435
          runtime( "Setting int attribute to non-int value" );
436
        l->attrs[0].u.data = v1.val.i;
437
        break;
438
      case EAF_TYPE_AS_PATH:
439
        if (v1.type != T_PATH)
440
          runtime( "Setting path attribute to non-path value" );
441
        l->attrs[0].u.ptr = v1.val.ad;
442
        break;
443
      case EAF_TYPE_INT_SET:
444
        if (v1.type != T_CLIST)
445
          runtime( "Setting int set  attribute to non-clist value" );
446
        l->attrs[0].u.ptr = v1.val.ad;
447
        break;
448
      case EAF_TYPE_UNDEF:
449
        if (v1.type != T_VOID)
450
          runtime( "Setting void attribute to non-void value" );
451
        l->attrs[0].u.data = 0;
452
        break;
453
      default: bug("Unknown type in e,S");
454
      }
455

    
456
      if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
457
        if (!f_rta_copy) {
458
          f_rta_copy = lp_alloc(f_pool, sizeof(rta));
459
          memcpy(f_rta_copy, (*f_rte)->attrs, sizeof(rta));
460
          f_rta_copy->aflags = 0;
461
          *f_rte = rte_cow(*f_rte);
462
          (*f_rte)->attrs = f_rta_copy;
463
        }
464
        l->next = f_rta_copy->eattrs;
465
        f_rta_copy->eattrs = l;
466
      } else {
467
        l->next = (*f_tmp_attrs);
468
        (*f_tmp_attrs) = l;
469
      }
470
    }
471
    break;
472

    
473
  case 'L':        /* Get length of */
474
    ONEARG;
475
    res.type = T_INT;
476
    switch(v1.type) {
477
    case T_PREFIX: res.val.i = v1.val.px.len; break;
478
    case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
479
    default: bug( "Length of what?" );
480
    }
481
    break;
482
  case P('c','p'):        /* Convert prefix to ... */
483
    ONEARG;
484
    if (v1.type != T_PREFIX)
485
      runtime( "Can not convert non-prefix this way" );
486
    res.type = what->aux;
487
    switch(res.type) {
488
      /*    case T_INT:        res.val.i = v1.val.px.len; break; Not needed any more */
489
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
490
    default: bug( "Unknown prefix to conversion" );
491
    }
492
    break;
493
  case 'r':
494
    ONEARG;
495
    res = v1;
496
    res.type |= T_RETURN;
497
    break;
498
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
499
    ONEARG;
500
    res = interpret(what->a2.p);
501
    if (res.type == T_RETURN)
502
      return res;
503
    res.type &= ~T_RETURN;    
504
    break;
505
  case P('S','W'):
506
    ONEARG;
507
    {
508
      struct f_tree *t = find_tree(what->a2.p, v1);
509
      if (!t) {
510
        v1.type = T_VOID;
511
        t = find_tree(what->a2.p, v1);
512
        if (!t) {
513
          debug( "No else statement?\n ");
514
          break;
515
        }
516
      }        
517
      if (!t->data)
518
        bug( "Impossible: no code associated!" );
519
      return interpret(t->data);
520
    }
521
    break;
522
  case P('i','M'): /* IP.MASK(val) */
523
    TWOARGS;
524
    if (v2.type != T_INT)
525
      runtime( "Can not use this type for mask.");
526
    if (v1.type != T_IP)
527
      runtime( "You can mask only IP addresses." );
528
    {
529
      ip_addr mask = ipa_mkmask(v2.val.i);
530
      res.type = T_IP;
531
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
532
    }
533
    break;
534

    
535
  case 'E':        /* Create empty attribute */
536
    res.type = what->aux;
537
    res.val.ad = adata_empty(f_pool);
538
    break;
539
  case P('A','p'):        /* Path prepend */
540
    TWOARGS;
541
    if (v1.type != T_PATH)
542
      runtime("Can't prepend to non-path");
543
    if (v2.type != T_INT)
544
      runtime("Can't prepend non-integer");
545

    
546
    res.type = T_PATH;
547
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
548
    break;
549

    
550
  case P('C','a'):        /* Community list add or delete */
551
    TWOARGS;
552
    if (v1.type != T_CLIST)
553
      runtime("Can't add/delete to non-clist");
554
    if (v2.type != T_PAIR)
555
      runtime("Can't add/delete non-pair");
556

    
557
    res.type = T_CLIST;
558
    switch (what->aux) {
559
    case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, v2.val.i); break;
560
    case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, v2.val.i); break;
561
    default: bug("unknown Ca operation");
562
    }
563
    break;
564

    
565
  default:
566
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
567
  }
568
  if (what->next)
569
    return interpret(what->next);
570
  return res;
571
}
572

    
573
#undef ARG
574
#define ARG(x,y) \
575
        if (!i_same(f1->y, f2->y)) \
576
                return 0;
577

    
578
#define ONEARG ARG(v1, a1.p)
579
#define TWOARGS ARG(v1, a1.p) \
580
                ARG(v2, a2.p)
581

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

    
584
int
585
i_same(struct f_inst *f1, struct f_inst *f2)
586
{
587
  if ((!!f1) != (!!f2))
588
    return 0;
589
  if (!f1)
590
    return 1;
591
  if (f1->aux != f2->aux)
592
    return 0;
593
  if (f1->code != f2->code)
594
    return 0;
595
  if (f1 == f2)                /* It looks strange, but it is possible with call rewriting trickery */
596
    return 1;
597

    
598
  switch(f1->code) {
599
  case ',': /* fall through */
600
  case '+':
601
  case '-':
602
  case '*':
603
  case '/':
604
  case P('!','='):
605
  case P('=','='):
606
  case '<':
607
  case P('<','='): TWOARGS; break;
608

    
609
  case '!': ONEARG; break;
610
  case '~': TWOARGS; break;
611
  case P('d','e'): ONEARG; break;
612

    
613
  case 's':
614
    ARG(v2, a2.p);
615
    {
616
      struct symbol *s1, *s2;
617
      s1 = f1->a1.p;
618
      s2 = f2->a1.p;
619
      if (strcmp(s1->name, s2->name))
620
        return 0;
621
      if (s1->class != s2->class)
622
        return 0;
623
    }
624
    break;
625

    
626
  case 'c': A2_SAME; break;
627
  case 'C': 
628
    if (val_compare(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
629
      return 0;
630
    break;
631
  case 'p': case 'L': ONEARG; break;
632
  case '?': TWOARGS; break;
633
  case '0': case 'E': break;
634
  case P('p',','): ONEARG; A2_SAME; break;
635
  case 'a': A2_SAME; break;
636
  case P('e','a'): A2_SAME; break;
637
  case P('e','S'): ONEARG; A2_SAME; break;
638

    
639
  case 'r': ONEARG; break;
640
  case P('c','p'): ONEARG; break;
641
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
642
             ONEARG; 
643
             if (!i_same(f1->a2.p, f2->a2.p))
644
               return 0; 
645
             f2->a2.p = f1->a2.p;
646
             break;
647
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
648
  case P('i','M'): TWOARGS; break;
649
  case P('A','p'): TWOARGS; break;
650
  case P('C','a'): TWOARGS; break;
651
  default:
652
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
653
  }
654
  return i_same(f1->next, f2->next);
655
}
656

    
657
/**
658
 * f_run - external entry point to filters
659
 * @filter: pointer to filter to run
660
 * @rte: pointer to pointer to rte being filtered. When route is modified, this is changed with rte_cow.
661
 * @tmp_pool: all filter allocations go from this pool
662
 */
663
int
664
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
665
{
666
  struct f_inst *inst;
667
  struct f_val res;
668
  DBG( "Running filter `%s'...", filter->name );
669

    
670
  f_flags = flags;
671
  f_tmp_attrs = tmp_attrs;
672
  f_rte = rte;
673
  f_rte_old = *rte;
674
  f_rta_copy = NULL;
675
  f_pool = tmp_pool;
676
  inst = filter->root;
677
  res = interpret(inst);
678
  if (res.type != T_RETURN)
679
    return F_ERROR;
680
  DBG( "done (%d)\n", res.val.i );
681
  return res.val.i;
682
}
683

    
684
int
685
f_eval_int(struct f_inst *expr)
686
{
687
  struct f_val res;
688

    
689
  f_flags = 0;
690
  f_tmp_attrs = NULL;
691
  f_rte = NULL;
692
  f_rte_old = NULL;
693
  f_rta_copy = NULL;
694
  f_pool = cfg_mem;
695
  res = interpret(expr);
696
  if (res.type != T_INT)
697
    cf_error("Integer expression expected");
698
  return res.val.i;
699
}
700

    
701
/**
702
 * filter_same - compare two filters
703
 * @new: first filter to be compared
704
 * @old: second filter to be compared, notice that this filter is
705
 * damaged while comparing.
706
 *
707
 * Returns 1 in case filters are same, otherwise 0. If there are
708
 * underlying bugs, it will rather say 0 on same filters than say
709
 * 1 on different.
710
 */
711
int
712
filter_same(struct filter *new, struct filter *old)
713
{
714
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
715
    return 1;
716
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
717
      new == FILTER_ACCEPT || new == FILTER_REJECT)
718
    return 0;
719
  return i_same(new->root, old->root);
720
}
721

    
722
struct adata *
723
adata_empty(struct linpool *pool)
724
{
725
  struct adata *res = lp_alloc(pool, sizeof(struct adata));
726
  res->length = 0;
727
  return res;
728
}