Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 11cb6202

History | View | Annotate | Download (22.8 KB)

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

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

    
34
#undef LOCAL_DEBUG
35

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

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

    
51
#define CMP_ERROR 999
52

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

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

    
72
static void
73
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
74
{
75
  byte *end = buf + size - 16;
76

    
77
  while (p)
78
    {
79
      if (buf > end)
80
        {
81
          strcpy(buf, " ...");
82
          return;
83
        }
84

    
85
      if (p->any)
86
        buf += bsprintf(buf, "? ");
87
      else
88
        buf += bsprintf(buf, "%u ", p->val);
89

    
90
      p = p->next;
91
    }
92

    
93
  *buf = 0;
94
}
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 999 on error.
102
 * Tree module relies on this giving consistent results so that it can
103
 * build balanced trees.
104
 */
105
int
106
val_compare(struct f_val v1, struct f_val v2)
107
{
108
  int rc;
109

    
110
  if ((v1.type == T_VOID) && (v2.type == T_VOID))
111
    return 0;
112
  if (v1.type == T_VOID)        /* Hack for else */
113
    return -1;
114
  if (v2.type == T_VOID)
115
    return 1;
116

    
117
  if (v1.type != v2.type) {
118
    debug( "Types do not match in val_compare\n" );
119
    return CMP_ERROR;
120
  }
121
  switch (v1.type) {
122
  case T_ENUM:
123
  case T_INT: 
124
  case T_PAIR:
125
    if (v1.val.i == v2.val.i) return 0;
126
    if (v1.val.i < v2.val.i) return -1;
127
    return 1;
128
  case T_IP:
129
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
130
  case T_PREFIX:
131
    if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
132
      return rc;
133
    if (v1.val.px.len < v2.val.px.len)
134
      return -1;
135
    if (v1.val.px.len > v2.val.px.len)
136
      return 1;
137
    return 0;
138
  case T_PATH_MASK:
139
    return pm_path_compare(v1.val.path_mask, v2.val.path_mask);
140
  default:
141
    debug( "Compare of unkown entities: %x\n", v1.type );
142
    return CMP_ERROR;
143
  }
144
}
145

    
146
/*
147
 * val_simple_in_range - check if @v1 ~ @v2 for everything except sets
148
 */ 
149
static int
150
val_simple_in_range(struct f_val v1, struct f_val v2)
151
{
152
  if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
153
    return as_path_match(v1.val.ad, v2.val.path_mask);
154
  if ((v1.type == T_PAIR) && (v2.type == T_CLIST))
155
    return int_set_contains(v2.val.ad, v1.val.i);
156

    
157
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
158
    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))));
159

    
160
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) {
161
    ip_addr mask;
162
    if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE))
163
      return CMP_ERROR;
164
    mask = ipa_mkmask( v2.val.px.len & LEN_MASK );
165
    if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask)))
166
      return 0;
167

    
168
    if ((v2.val.px.len & LEN_MINUS) && (v1.val.px.len <= (v2.val.px.len & LEN_MASK)))
169
      return 0;
170
    if ((v2.val.px.len & LEN_PLUS) && (v1.val.px.len < (v2.val.px.len & LEN_MASK)))
171
      return 0;
172
    if ((v2.val.px.len & LEN_RANGE) && ((v1.val.px.len < (0xff & (v2.val.px.len >> 16)))
173
                                        || (v1.val.px.len > (0xff & (v2.val.px.len >> 8)))))
174
      return 0;
175
    return 1;    
176
  }
177
  return CMP_ERROR;
178
}
179

    
180
/**
181
 * val_in_range - implement |~| operator
182
 * @v1: element
183
 * @v2: set
184
 *
185
 * Checks if @v1 is element (|~| operator) of @v2. Sets are internally represented as balanced trees, see
186
 * |tree.c| module (this is not limited to sets, but for non-set cases, val_simple_in_range() is called early).
187
 */
188
static int
189
val_in_range(struct f_val v1, struct f_val v2)
190
{
191
  int res;
192

    
193
  res = val_simple_in_range(v1, v2);
194

    
195
  if (res != CMP_ERROR)
196
    return res;
197
  
198
  if (v2.type == T_SET)
199
    switch (v1.type) {
200
    case T_ENUM:
201
    case T_INT:
202
    case T_IP:
203
    case T_PREFIX:
204
      {
205
        struct f_tree *n;
206
        n = find_tree(v2.val.t, v1);
207
        if (!n)
208
          return 0;
209
        return !! (val_simple_in_range(v1, n->from));        /* We turn CMP_ERROR into compared ok, and that's fine */
210
      }
211
    }
212
  return CMP_ERROR;
213
}
214

    
215
static void
216
tree_print(struct f_tree *t)
217
{
218
  if (!t) {
219
    debug( "() " );
220
    return;
221
  }
222
  debug( "[ " );
223
  tree_print( t->left );
224
  debug( ", " ); val_print( t->from ); debug( ".." ); val_print( t->to ); debug( ", " );
225
  tree_print( t->right );
226
  debug( "] " );
227
}
228

    
229
/*
230
 * val_print - format filter value
231
 */
232
void
233
val_print(struct f_val v)
234
{
235
  char buf[2048];
236
  char buf2[1024];
237
#define PRINTF(a...) bsnprintf( buf, 2040, a )
238
  buf[0] = 0;
239
  switch (v.type) {
240
  case T_VOID: PRINTF( "(void)" ); break;
241
  case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
242
  case T_INT: PRINTF( "%d ", v.val.i ); break;
243
  case T_STRING: PRINTF( "%s", v.val.s ); break;
244
  case T_IP: PRINTF( "%I", v.val.px.ip ); break;
245
  case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
246
  case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
247
  case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
248
  case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
249
  case T_PATH: as_path_format(v.val.ad, buf2, 1020); PRINTF( "(path %s)", buf2 ); break;
250
  case T_CLIST: int_set_format(v.val.ad, buf2, 1020); PRINTF( "(clist %s)", buf2 ); break;
251
  case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1020); PRINTF( "(pathmask %s)", buf2 ); break;
252
  default: PRINTF( "[unknown type %x]", v.type );
253
#undef PRINTF
254
  }
255
  debug( buf );
256
}
257

    
258
static struct rte **f_rte, *f_rte_old;
259
static struct linpool *f_pool;
260
static struct ea_list **f_tmp_attrs;
261
static int f_flags;
262
static rta *f_rta_copy;
263

    
264
/*
265
 * rta_cow - prepare rta for modification by filter
266
 */
267
static void
268
rta_cow(void)
269
{
270
  if (!f_rta_copy) {
271
    f_rta_copy = lp_alloc(f_pool, sizeof(rta));
272
    memcpy(f_rta_copy, (*f_rte)->attrs, sizeof(rta));
273
    f_rta_copy->aflags = 0;
274
    *f_rte = rte_cow(*f_rte);
275
    rta_free((*f_rte)->attrs);
276
    (*f_rte)->attrs = f_rta_copy;
277
  }
278
}
279

    
280
#define runtime(x) do { \
281
    log( L_ERR "filters, line %d: %s", what->lineno, x); \
282
    res.type = T_RETURN; \
283
    res.val.i = F_ERROR; \
284
    return res; \
285
  } while(0)
286

    
287
#define ARG(x,y) \
288
        x = interpret(what->y); \
289
        if (x.type & T_RETURN) \
290
                return x;
291

    
292
#define ONEARG ARG(v1, a1.p)
293
#define TWOARGS ARG(v1, a1.p) \
294
                ARG(v2, a2.p)
295
#define TWOARGS_C TWOARGS \
296
                  if (v1.type != v2.type) \
297
                    runtime( "Can't operate with values of incompatible types" );
298

    
299
/**
300
 * interpret
301
 * @what: filter to interpret
302
 *
303
 * Interpret given tree of filter instructions. This is core function
304
 * of filter system and does all the hard work.
305
 *
306
 * Each instruction has 4 fields: code (which is instruction code),
307
 * aux (which is extension to instruction code, typically type),
308
 * arg1 and arg2 - arguments. Depending on instruction, arguments
309
 * are either integers, or pointers to instruction trees. Common 
310
 * instructions like +, that have two expressions as arguments use
311
 * TWOARGS macro to get both of them evaluated.
312
 *
313
 * &f_val structures are copied around, so there are no problems with
314
 * memory managment.
315
 */
316
static struct f_val
317
interpret(struct f_inst *what)
318
{
319
  struct symbol *sym;
320
  struct f_val v1, v2, res;
321
  int i;
322

    
323
  res.type = T_VOID;
324
  if (!what)
325
    return res;
326

    
327
  switch(what->code) {
328
  case ',':
329
    TWOARGS;
330
    break;
331

    
332
/* Binary operators */
333
  case '+':
334
    TWOARGS_C;
335
    switch (res.type = v1.type) {
336
    case T_VOID: runtime( "Can't operate with values of type void" );
337
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
338
    default: runtime( "Usage of unknown type" );
339
    }
340
    break;
341
  case '-':
342
    TWOARGS_C;
343
    switch (res.type = v1.type) {
344
    case T_VOID: runtime( "Can't operate with values of type void" );
345
    case T_INT: res.val.i = v1.val.i - v2.val.i; break;
346
    default: runtime( "Usage of unknown type" );
347
    }
348
    break;
349
  case '*':
350
    TWOARGS_C;
351
    switch (res.type = v1.type) {
352
    case T_VOID: runtime( "Can't operate with values of type void" );
353
    case T_INT: res.val.i = v1.val.i * v2.val.i; break;
354
    default: runtime( "Usage of unknown type" );
355
    }
356
    break;
357
  case '/':
358
    TWOARGS_C;
359
    switch (res.type = v1.type) {
360
    case T_VOID: runtime( "Can't operate with values of type void" );
361
    case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
362
                      res.val.i = v1.val.i / v2.val.i; break;
363
    case T_IP: if (v2.type != T_INT)
364
                 runtime( "Incompatible types in / operator" );
365
               break;
366
    default: runtime( "Usage of unknown type" );
367
    }
368
    break;
369
    
370
  case '&':
371
    TWOARGS_C;
372
    res.type = v1.type;
373
    if (res.type != T_BOOL) runtime( "Can't do boolean operation on non-booleans" );
374
    res.val.i = v1.val.i && v2.val.i;
375
    break;
376
  case '|':
377
    TWOARGS_C;
378
    res.type = v1.type;
379
    if (res.type != T_BOOL) runtime( "Can't do boolean operation on non-booleans" );
380
    res.val.i = v1.val.i || v2.val.i;
381
    break;
382

    
383
/* Relational operators */
384

    
385
#define COMPARE(x) \
386
    TWOARGS_C; \
387
    res.type = T_BOOL; \
388
    i = val_compare(v1, v2); \
389
    if (i==CMP_ERROR) \
390
      runtime( "Error in comparison" ); \
391
    res.val.i = (x); \
392
    break;
393

    
394
  case P('!','='): COMPARE(i!=0);
395
  case P('=','='): COMPARE(i==0);
396
  case '<': COMPARE(i==-1);
397
  case P('<','='): COMPARE(i!=1);
398

    
399
  case '!':
400
    ONEARG;
401
    if (v1.type != T_BOOL)
402
      runtime( "Not applied to non-boolean" );
403
    res = v1;
404
    res.val.i = !res.val.i;
405
    break;
406

    
407
  case '~':
408
    TWOARGS;
409
    res.type = T_BOOL;
410
    res.val.i = val_in_range(v1, v2);
411
    if (res.val.i == CMP_ERROR)
412
      runtime( "~ applied on unknown type pair" );
413
    break;
414
  case P('d','e'):
415
    ONEARG;
416
    res.type = T_BOOL;
417
    res.val.i = (v1.type != T_VOID);
418
    break;
419

    
420
  /* Set to indirect value, a1 = variable, a2 = value */
421
  case 's':
422
    ARG(v2, a2.p);
423
    sym = what->a1.p;
424
    switch (res.type = v2.type) {
425
    case T_VOID: runtime( "Can't assign void values" );
426
    case T_ENUM:
427
    case T_INT: 
428
    case T_IP: 
429
    case T_PREFIX: 
430
    case T_PAIR: 
431
    case T_PATH:
432
    case T_CLIST:
433
    case T_PATH_MASK:
434
      if (sym->class != (SYM_VARIABLE | v2.type))
435
        runtime( "Assigning to variable of incompatible type" );
436
      * (struct f_val *) sym->aux2 = v2; 
437
      break;
438
    default:
439
      bug( "Set to invalid type" );
440
    }
441
    break;
442

    
443
  case 'c':        /* integer (or simple type) constant */
444
    res.type = what->aux;
445
    res.val.i = what->a2.i;
446
    break;
447
  case 'C':
448
    res = * ((struct f_val *) what->a1.p);
449
    break;
450
  case 'p':
451
    ONEARG;
452
    val_print(v1);
453
    break;
454
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
455
    ONEARG;
456
    if (v1.type != T_BOOL)
457
      runtime( "If requires boolean expression" );
458
    if (v1.val.i) {
459
      ARG(res,a2.p);
460
      res.val.i = 0;
461
    } else res.val.i = 1;
462
    res.type = T_BOOL;
463
    break;
464
  case '0':
465
    debug( "No operation\n" );
466
    break;
467
  case P('p',','):
468
    ONEARG;
469
    if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
470
      debug( "\n" );
471

    
472
    switch (what->a2.i) {
473
    case F_QUITBIRD:
474
      die( "Filter asked me to die" );
475
    case F_ACCEPT:
476
      /* Should take care about turning ACCEPT into MODIFY */
477
    case F_ERROR:
478
    case F_REJECT:        /* FIXME (noncritical) Should print complete route along with reason to reject route */
479
      res.type = T_RETURN;
480
      res.val.i = what->a2.i;
481
      return res;        /* We have to return now, no more processing. */
482
    case F_NONL:
483
    case F_NOP:
484
      break;
485
    default:
486
      bug( "unknown return type: Can't happen");
487
    }
488
    break;
489
  case 'a':        /* rta access */
490
    {
491
      struct rta *rta = (*f_rte)->attrs;
492
      res.type = what->aux;
493
      switch(res.type) {
494
      case T_IP:
495
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
496
        break;
497
      case T_ENUM:
498
        res.val.i = * ((char *) rta + what->a2.i);
499
        break;
500
      case T_PREFIX:        /* Warning: this works only for prefix of network */
501
        {
502
          res.val.px.ip = (*f_rte)->net->n.prefix;
503
          res.val.px.len = (*f_rte)->net->n.pxlen;
504
          break;
505
        }
506
      default:
507
        bug( "Invalid type for rta access (%x)", res.type );
508
      }
509
    }
510
    break;
511
  case P('a','S'):
512
    ONEARG;
513
    if (what->aux != v1.type)
514
      runtime( "Attempt to set static attribute to incompatible type" );
515
    rta_cow();
516
    {
517
      struct rta *rta = (*f_rte)->attrs;
518
      switch (what->aux) {
519
      case T_ENUM:
520
        * ((char *) rta + what->a2.i) = v1.val.i;
521
        break;
522
      case T_IP:
523
        * (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip;
524
        break;
525
      default:
526
        bug( "Unknown type in set of static attribute" );
527
      }
528
    }
529
    break;
530
  case P('e','a'):        /* Access to extended attributes */
531
    {
532
      eattr *e = NULL;
533
      if (!(f_flags & FF_FORCE_TMPATTR))
534
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
535
      if (!e) 
536
        e = ea_find( (*f_tmp_attrs), what->a2.i );
537
      if ((!e) && (f_flags & FF_FORCE_TMPATTR))
538
        e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
539
      
540
      switch (what->aux & EAF_TYPE_MASK) {
541
      case EAF_TYPE_INT:
542
        if (!e) {
543
          res.type = T_VOID;
544
          break;
545
        }
546
        res.type = T_INT;
547
        res.val.i = e->u.data;
548
        break;
549
      case EAF_TYPE_AS_PATH:
550
        if (!e) {
551
          res.type = T_VOID;
552
          break;
553
        }
554
        res.type = T_PATH;
555
        res.val.ad = e->u.ptr;
556
        break;
557
      case EAF_TYPE_INT_SET:
558
        if (!e) {
559
          res.type = T_CLIST;
560
          res.val.ad = adata_empty(f_pool);
561
          break;
562
        }
563
        res.type = T_CLIST;
564
        res.val.ad = e->u.ptr;
565
        break;
566
      default:
567
        bug("Unknown type in e,a");
568
      }
569
    }
570
    break;
571
  case P('e','S'):
572
    ONEARG;
573
    {
574
      struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
575

    
576
      l->next = NULL;
577
      l->flags = EALF_SORTED;
578
      l->count = 1;
579
      l->attrs[0].id = what->a2.i;
580
      l->attrs[0].flags = 0;
581
      l->attrs[0].type = what->aux | EAF_ORIGINATED;
582
      switch (what->aux & EAF_TYPE_MASK) {
583
      case EAF_TYPE_INT:
584
        if (v1.type != T_INT)
585
          runtime( "Setting int attribute to non-int value" );
586
        l->attrs[0].u.data = v1.val.i;
587
        break;
588
      case EAF_TYPE_AS_PATH:
589
        if (v1.type != T_PATH)
590
          runtime( "Setting path attribute to non-path value" );
591
        l->attrs[0].u.ptr = v1.val.ad;
592
        break;
593
      case EAF_TYPE_INT_SET:
594
        if (v1.type != T_CLIST)
595
          runtime( "Setting int set attribute to non-clist value" );
596
        l->attrs[0].u.ptr = v1.val.ad;
597
        break;
598
      case EAF_TYPE_UNDEF:
599
        if (v1.type != T_VOID)
600
          runtime( "Setting void attribute to non-void value" );
601
        l->attrs[0].u.data = 0;
602
        break;
603
      default: bug("Unknown type in e,S");
604
      }
605

    
606
      if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
607
        rta_cow();
608
        l->next = f_rta_copy->eattrs;
609
        f_rta_copy->eattrs = l;
610
      } else {
611
        l->next = (*f_tmp_attrs);
612
        (*f_tmp_attrs) = l;
613
      }
614
    }
615
    break;
616
  case 'P':
617
    res.type = T_INT;
618
    res.val.i = (*f_rte)->pref;
619
    break;
620
  case P('P','S'):
621
    ONEARG;
622
    if (v1.type != T_INT)
623
      runtime( "Can't set preference to non-integer" );
624
    *f_rte = rte_cow(*f_rte);
625
    (*f_rte)->pref = v1.val.i;
626
    break;
627
  case 'L':        /* Get length of */
628
    ONEARG;
629
    res.type = T_INT;
630
    switch(v1.type) {
631
    case T_PREFIX: res.val.i = v1.val.px.len; break;
632
    case T_PATH:   res.val.i = as_path_getlen(v1.val.ad); break;
633
    default: bug( "Length of what?" );
634
    }
635
    break;
636
  case P('c','p'):        /* Convert prefix to ... */
637
    ONEARG;
638
    if (v1.type != T_PREFIX)
639
      runtime( "Prefix expected" );
640
    res.type = what->aux;
641
    switch(res.type) {
642
      /*    case T_INT:        res.val.i = v1.val.px.len; break; Not needed any more */
643
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
644
    default: bug( "Unknown prefix to conversion" );
645
    }
646
    break;
647
  case 'r':
648
    ONEARG;
649
    res = v1;
650
    res.type |= T_RETURN;
651
    break;
652
  case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out  */
653
    ONEARG;
654
    res = interpret(what->a2.p);
655
    if (res.type == T_RETURN)
656
      return res;
657
    res.type &= ~T_RETURN;    
658
    break;
659
  case P('S','W'):
660
    ONEARG;
661
    {
662
      struct f_tree *t = find_tree(what->a2.p, v1);
663
      if (!t) {
664
        v1.type = T_VOID;
665
        t = find_tree(what->a2.p, v1);
666
        if (!t) {
667
          debug( "No else statement?\n");
668
          break;
669
        }
670
      }        
671
      /* It is actually possible to have t->data NULL */
672
      return interpret(t->data);
673
    }
674
    break;
675
  case P('i','M'): /* IP.MASK(val) */
676
    TWOARGS;
677
    if (v2.type != T_INT)
678
      runtime( "Integer expected");
679
    if (v1.type != T_IP)
680
      runtime( "You can mask only IP addresses" );
681
    {
682
      ip_addr mask = ipa_mkmask(v2.val.i);
683
      res.type = T_IP;
684
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
685
    }
686
    break;
687

    
688
  case 'E':        /* Create empty attribute */
689
    res.type = what->aux;
690
    res.val.ad = adata_empty(f_pool);
691
    break;
692
  case P('A','p'):        /* Path prepend */
693
    TWOARGS;
694
    if (v1.type != T_PATH)
695
      runtime("Can't prepend to non-path");
696
    if (v2.type != T_INT)
697
      runtime("Can't prepend non-integer");
698

    
699
    res.type = T_PATH;
700
    res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
701
    break;
702

    
703
  case P('C','a'):        /* Community list add or delete */
704
    TWOARGS;
705
    if (v1.type != T_CLIST)
706
      runtime("Can't add/delete to non-clist");
707
    if (v2.type != T_PAIR)
708
      runtime("Can't add/delete non-pair");
709

    
710
    res.type = T_CLIST;
711
    switch (what->aux) {
712
    case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, v2.val.i); break;
713
    case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, v2.val.i); break;
714
    default: bug("unknown Ca operation");
715
    }
716
    break;
717

    
718
  default:
719
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
720
  }
721
  if (what->next)
722
    return interpret(what->next);
723
  return res;
724
}
725

    
726
#undef ARG
727
#define ARG(x,y) \
728
        if (!i_same(f1->y, f2->y)) \
729
                return 0;
730

    
731
#define ONEARG ARG(v1, a1.p)
732
#define TWOARGS ARG(v1, a1.p) \
733
                ARG(v2, a2.p)
734

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

    
737
/*
738
 * i_same - function that does real comparing of instruction trees, you should call filter_same from outside
739
 */
740
int
741
i_same(struct f_inst *f1, struct f_inst *f2)
742
{
743
  if ((!!f1) != (!!f2))
744
    return 0;
745
  if (!f1)
746
    return 1;
747
  if (f1->aux != f2->aux)
748
    return 0;
749
  if (f1->code != f2->code)
750
    return 0;
751
  if (f1 == f2)                /* It looks strange, but it is possible with call rewriting trickery */
752
    return 1;
753

    
754
  switch(f1->code) {
755
  case ',': /* fall through */
756
  case '+':
757
  case '-':
758
  case '*':
759
  case '/':
760
  case '|':
761
  case '&':
762
  case P('!','='):
763
  case P('=','='):
764
  case '<':
765
  case P('<','='): TWOARGS; break;
766

    
767
  case '!': ONEARG; break;
768
  case '~': TWOARGS; break;
769
  case P('d','e'): ONEARG; break;
770

    
771
  case 's':
772
    ARG(v2, a2.p);
773
    {
774
      struct symbol *s1, *s2;
775
      s1 = f1->a1.p;
776
      s2 = f2->a1.p;
777
      if (strcmp(s1->name, s2->name))
778
        return 0;
779
      if (s1->class != s2->class)
780
        return 0;
781
    }
782
    break;
783

    
784
  case 'c': 
785
    if (f1->aux & T_SET) {
786
      if (!same_tree(f1->a2.p, f2->a2.p))
787
        return 0;
788
      break;
789
    } 
790
    switch (f1->aux) {
791
    case T_STRING:
792
      if (strcmp(f1->a2.p, f2->a2.p))
793
        return 0;
794
      break;
795
    default:
796
      A2_SAME;
797
    }
798
    break;
799
  case 'C': 
800
    if (val_compare(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
801
      return 0;
802
    break;
803
  case 'p': case 'L': ONEARG; break;
804
  case '?': TWOARGS; break;
805
  case '0': case 'E': break;
806
  case P('p',','): ONEARG; A2_SAME; break;
807
  case 'P':
808
  case 'a': A2_SAME; break;
809
  case P('e','a'): A2_SAME; break;
810
  case P('P','S'):
811
  case P('a','S'):
812
  case P('e','S'): ONEARG; A2_SAME; break;
813

    
814
  case 'r': ONEARG; break;
815
  case P('c','p'): ONEARG; break;
816
  case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
817
             ONEARG; 
818
             if (!i_same(f1->a2.p, f2->a2.p))
819
               return 0; 
820
             f2->a2.p = f1->a2.p;
821
             break;
822
  case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
823
  case P('i','M'): TWOARGS; break;
824
  case P('A','p'): TWOARGS; break;
825
  case P('C','a'): TWOARGS; break;
826
  default:
827
    bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
828
  }
829
  return i_same(f1->next, f2->next);
830
}
831

    
832
/**
833
 * f_run - external entry point to filters
834
 * @filter: pointer to filter to run
835
 * @tmp_attrs: where to store newly generated temporary attributes
836
 * @rte: pointer to pointer to &rte being filtered. When route is modified, this is changed with rte_cow().
837
 * @tmp_pool: all filter allocations go from this pool
838
 * @flags: flags
839
 */
840
int
841
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
842
{
843
  struct f_inst *inst;
844
  struct f_val res;
845
  DBG( "Running filter `%s'...", filter->name );
846

    
847
  f_flags = flags;
848
  f_tmp_attrs = tmp_attrs;
849
  f_rte = rte;
850
  f_rte_old = *rte;
851
  f_rta_copy = NULL;
852
  f_pool = tmp_pool;
853
  inst = filter->root;
854
  res = interpret(inst);
855
  if (res.type != T_RETURN) {
856
    log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name); 
857
    return F_ERROR;
858
  }
859
  DBG( "done (%d)\n", res.val.i );
860
  return res.val.i;
861
}
862

    
863
int
864
f_eval_int(struct f_inst *expr)
865
{
866
  struct f_val res;
867

    
868
  f_flags = 0;
869
  f_tmp_attrs = NULL;
870
  f_rte = NULL;
871
  f_rte_old = NULL;
872
  f_rta_copy = NULL;
873
  f_pool = cfg_mem;
874
  res = interpret(expr);
875
  if (res.type != T_INT)
876
    cf_error("Integer expression expected");
877
  return res.val.i;
878
}
879

    
880
/**
881
 * filter_same - compare two filters
882
 * @new: first filter to be compared
883
 * @old: second filter to be compared, notice that this filter is
884
 * damaged while comparing.
885
 *
886
 * Returns 1 in case filters are same, otherwise 0. If there are
887
 * underlying bugs, it will rather say 0 on same filters than say
888
 * 1 on different.
889
 */
890
int
891
filter_same(struct filter *new, struct filter *old)
892
{
893
  if (old == new)        /* Handle FILTER_ACCEPT and FILTER_REJECT */
894
    return 1;
895
  if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
896
      new == FILTER_ACCEPT || new == FILTER_REJECT)
897
    return 0;
898
  return i_same(new->root, old->root);
899
}