Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 2f702671

History | View | Annotate | Download (9.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
 *         Notice that pair is stored as integer: first << 16 | second
9
 *
10
 *        FIXME: Check if prefixes are really prefixes.
11
 */
12

    
13
#include <stdio.h>
14
#include <fcntl.h>
15
#include <unistd.h>
16
#include <sys/signal.h>
17
#include <setjmp.h>
18

    
19
#include "nest/bird.h"
20
#include "lib/lists.h"
21
#include "lib/resource.h"
22
#include "lib/socket.h"
23
#include "lib/string.h"
24
#include "nest/route.h"
25
#include "nest/protocol.h"
26
#include "nest/iface.h"
27
#include "conf/conf.h"
28
#include "filter/filter.h"
29

    
30
struct f_inst *startup_func = NULL;
31

    
32
#define runtime(x) do { \
33
    log( L_ERR x ); \
34
    res.type = T_RETURN; \
35
    res.val.i = F_ERROR; \
36
    return res; \
37
  } while(0)
38

    
39
#define ARG(x,y) \
40
        x = interpret(what->y); \
41
        if (x.type == T_RETURN) \
42
                return x;
43

    
44
#define ONEARG ARG(v1, a1.p)
45
#define TWOARGS ARG(v1, a1.p) \
46
                ARG(v2, a2.p)
47
#define TWOARGS_C TWOARGS \
48
                  if (v1.type != v2.type) \
49
                    runtime( "Can not operate with values of incompatible types" );
50

    
51
#define CMP_ERROR 999
52

    
53
/* Compare two values, returns -1, 0, 1 compared, ERROR 999 */
54
int
55
val_compare(struct f_val v1, struct f_val v2)
56
{
57
  if ((v1.type == T_VOID) && (v2.type == T_VOID))
58
    return 0;
59
  if (v1.type == T_VOID)        /* Hack for else */
60
    return -1;
61
  if (v2.type == T_VOID)
62
    return 1;
63

    
64
  if (v1.type != v2.type)
65
    return CMP_ERROR;
66
  switch (v1.type) {
67
  case T_ENUM:
68
  case T_INT: 
69
  case T_PAIR:
70
    if (v1.val.i == v2.val.i) return 0;
71
    if (v1.val.i < v2.val.i) return -1;
72
    return 1;
73
  case T_IP:
74
  case T_PREFIX:
75
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
76
  default: { printf( "Error comparing\n" ); return CMP_ERROR; }
77
  }
78
}
79

    
80
int 
81
val_simple_in_range(struct f_val v1, struct f_val v2)
82
{
83
  if ((v1.type == T_IP) && (v2.type == T_PREFIX))
84
    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))));
85

    
86
  if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) {
87
    ip_addr mask;
88
    if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE))
89
      return CMP_ERROR;
90
    mask = ipa_mkmask( v2.val.px.len & LEN_MASK );
91
    if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask)))
92
      return 0;
93
    /* FIXME: read rpsl or better ask mj: is it really like this? */
94
    if ((v2.val.px.len & LEN_MINUS) && (v1.val.px.len <= (v2.val.px.len & LEN_MASK)))
95
      return 0;
96
    if ((v2.val.px.len & LEN_PLUS) && (v1.val.px.len < (v2.val.px.len & LEN_MASK)))
97
      return 0;
98
    if ((v2.val.px.len & LEN_RANGE) && ((v1.val.px.len < (0xff & (v2.val.px.len >> 16)))
99
                                        || (v1.val.px.len > (0xff & (v2.val.px.len >> 8)))))
100
      return 0;
101
    return 1;    
102
  }
103
  return CMP_ERROR;
104
}
105

    
106
int
107
val_in_range(struct f_val v1, struct f_val v2)
108
{
109
  int res;
110

    
111
  res = val_simple_in_range(v1, v2);
112

    
113
  if (res != CMP_ERROR)
114
    return res;
115

    
116
  if (((v1.type == T_INT) || ((v1.type == T_IP) || (v1.type == T_PREFIX)) && (v2.type == T_SET))) {
117
    struct f_tree *n;
118
    n = find_tree(v2.val.t, v1);
119
    if (!n)
120
      return 0;
121
    return !! (val_simple_in_range(v1, n->from));        /* We turn CMP_ERROR into compared ok, and that's fine */
122
  }
123
  return CMP_ERROR;
124
}
125

    
126
static void
127
tree_print(struct f_tree *t)
128
{
129
  if (!t) {
130
    printf( "() " );
131
    return;
132
  }
133
  printf( "[ " );
134
  tree_print( t->left );
135
  printf( ", " ); val_print( t->from ); printf( ".." ); val_print( t->to ); printf( ", " );
136
  tree_print( t->right );
137
  printf( "] " );
138
}
139

    
140
void
141
val_print(struct f_val v)
142
{
143
  char buf[2048];
144
#define PRINTF(a...) bsnprintf( buf, 2040, a )
145
  buf[0] = 0;
146
  switch (v.type) {
147
  case T_VOID: PRINTF( "(void)" ); break;
148
  case T_BOOL: PRINTF( v.val.i ? "TRUE" : "FALSE" ); break;
149
  case T_INT: PRINTF( "%d ", v.val.i ); break;
150
  case T_STRING: PRINTF( "%s", v.val.s ); break;
151
  case T_IP: PRINTF( "%I", v.val.px.ip ); break;
152
  case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
153
  case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
154
  case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
155
  default: PRINTF( "[unknown type %x]", v.type );
156
  }
157
  printf( buf );
158
}
159

    
160
static struct rte **f_rte;
161

    
162
static struct f_val interpret(struct f_inst *what);
163

    
164
static struct f_val
165
interpret(struct f_inst *what)
166
{
167
  struct symbol *sym;
168
  struct f_val v1, v2, res;
169
  int i,j,k;
170

    
171
  res.type = T_VOID;
172
  if (!what)
173
    return res;
174

    
175
  switch(what->code) {
176
  case ',':
177
    TWOARGS;
178
    break;
179

    
180
/* Binary operators */
181
  case '+':
182
    TWOARGS_C;
183
    switch (res.type = v1.type) {
184
    case T_VOID: runtime( "Can not operate with values of type void" );
185
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
186
    default: runtime( "Usage of unknown type" );
187
    }
188
    break;
189
  case '/':
190
    TWOARGS_C;
191
    switch (res.type = v1.type) {
192
    case T_VOID: runtime( "Can not operate with values of type void" );
193
    case T_INT: res.val.i = v1.val.i / v2.val.i; break;
194
    case T_IP: if (v2.type != T_INT)
195
                 runtime( "Operator / is <ip>/<int>" );
196
               break;
197
    default: runtime( "Usage of unknown type" );
198
    }
199
    break;
200

    
201
/* Relational operators */
202

    
203
#define COMPARE(x) \
204
    TWOARGS_C; \
205
    res.type = T_BOOL; \
206
    i = val_compare(v1, v2); \
207
    if (i==CMP_ERROR) \
208
      runtime( "Error in comparation" ); \
209
    res.val.i = (x); \
210
    break;
211

    
212
  case '!=': COMPARE(i!=0);
213
  case '==': COMPARE(i==0);
214
  case '<': COMPARE(i==-1);
215
  case '<=': COMPARE(i!=1);
216

    
217
    /* FIXME: Should be able to work with prefixes of limited sizes */
218
  case '~':
219
    TWOARGS;
220
    res.type = T_BOOL;
221
    res.val.i = val_in_range(v1, v2);
222
    if (res.val.i == CMP_ERROR)
223
      runtime( "~ applied on unknown type pair" );
224
    break;
225
  case 'de':
226
    ONEARG;
227
    res.type = T_BOOL;
228
    res.val.i = (v1.type != T_VOID);
229
    break;
230

    
231
  /* Set to indirect value, a1 = variable, a2 = value */
232
  case 's':
233
    ARG(v2, a2.p);
234
    sym = what->a1.p;
235
    switch (res.type = v2.type) {
236
    case T_VOID: runtime( "Can not assign void values" );
237
    case T_ENUM:
238
    case T_INT: 
239
    case T_IP: 
240
    case T_PREFIX: 
241
    case T_PAIR: 
242
      if (sym->class != (SYM_VARIABLE | v2.type))
243
        runtime( "Variable of bad type" );
244
      * (struct f_val *) sym->aux2 = v2; 
245
      break;
246
    default:
247
      bug( "Set to invalid type\n" );
248
    }
249
    break;
250

    
251
  case 'c':        /* integer (or simple type) constant */
252
    res.type = what->a1.i;
253
    res.val.i = what->a2.i;
254
    break;
255
  case 'C':
256
    res = * ((struct f_val *) what->a1.p);
257
    break;
258
  case 'p':
259
    ONEARG;
260
    val_print(v1);
261
    break;
262
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
263
    ONEARG;
264
    if (v1.type != T_BOOL)
265
      runtime( "If requires bool expression" );
266
    if (v1.val.i) {
267
      ARG(res,a2.p);
268
      res.val.i = 0;
269
    } else res.val.i = 1;
270
    res.type = T_BOOL;
271
    break;
272
  case '0':
273
    printf( "No operation\n" );
274
    break;
275
  case 'p,':
276
    ONEARG;
277
    if (what->a2.i != F_NONL)
278
      printf( "\n" );
279

    
280
    switch (what->a2.i) {
281
    case F_QUITBIRD:
282
      die( "Filter asked me to die" );
283
    case F_ACCEPT:
284
      /* Should take care about turning ACCEPT into MODIFY */
285
    case F_ERROR:
286
    case F_REJECT:
287
      res.type = T_RETURN;
288
      res.val.i = what->a1.i;
289
      break;
290
    case F_NONL:
291
    case F_NOP:
292
      break;
293
    default:
294
      bug( "unknown return type: can not happen");
295
    }
296
    break;
297
  case 'a':        /* rta access */
298
    {
299
      struct rta *rta = (*f_rte)->attrs;
300
      res.type = what->a1.i;
301
      switch(res.type) {
302
      case T_IP:
303
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
304
        break;
305
      case T_PREFIX:        /* Warning: this works only for prefix of network */
306
        {
307
          res.val.px.ip = (*f_rte)->net->n.prefix;
308
          res.val.px.len = (*f_rte)->net->n.pxlen;
309
          break;
310
        }
311
      default:
312
        bug( "Invalid type for rta access" );
313
      }
314
    }
315
    break;
316
  case 'ea':        /* Access to extended attributes [hmm, but we need it read/write, do we?] */
317
    {
318
      eattr *e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
319
      if (!e) {
320
        res.type = T_VOID;
321
        break;
322
      }
323
      res.type = what->a1.i;
324
      switch (what->a1.i) {
325
      case T_INT:
326
        res.val.i = e->u.data;
327
        break;
328
      }
329
    }
330
    break;
331
  case 'cp':        /* Convert prefix to ... */
332
    ONEARG;
333
    if (v1.type != T_PREFIX)
334
      runtime( "Can not convert non-prefix this way" );
335
    res.type = what->a2.i;
336
    switch(res.type) {
337
    case T_INT:        res.val.i = v1.val.px.len; break;
338
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
339
    default: bug( "Unknown prefix to conversion\n" );
340
    }
341
    break;
342
  case 'ca': /* CALL */
343
    ONEARG;
344
    res = interpret(what->a2.p);
345
    break;
346
  case 'SW':
347
    ONEARG;
348
    {
349
      struct f_tree *t = find_tree(what->a2.p, v1);
350
      if (!t) {
351
        v1.type = T_VOID;
352
        t = find_tree(what->a2.p, v1);
353
        if (!t) {
354
          printf( "No else statement?\n ");
355
          break;
356
        }
357
      }        
358
      if (!t->data)
359
        die( "Impossible: no code associated!\n" );
360
      return interpret(t->data);
361
    }
362
    break;
363
  case 'iM': /* IP.MASK(val) */
364
    TWOARGS;
365
    if (v2.type != T_INT)
366
      runtime( "Can not use this type for mask.");
367
    if (v1.type != T_IP)
368
      runtime( "You can mask only IP addresses." );
369
    {
370
      ip_addr mask = ipa_mkmask(v2.val.i);
371
      res.type = T_IP;
372
      res.val.px.ip = ipa_and(mask, v1.val.px.ip);
373
    }
374
    break;
375
  default:
376
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
377
  }
378
  if (what->next)
379
    return interpret(what->next);
380
  return res;
381
}
382

    
383
int
384
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
385
{
386
  struct f_inst *inst;
387
  struct f_val res;
388
  debug( "Running filter `%s'...", filter->name );
389

    
390
  f_rte = rte;
391
  inst = filter->root;
392
  res = interpret(inst);
393
  if (res.type != T_RETURN)
394
    return F_ERROR;
395
  debug( "done (%d)\n", res.val.i );
396
  return res.val.i;
397
}
398

    
399

    
400
void
401
filters_postconfig(void)
402
{
403
  struct f_val res;
404
  if (startup_func) {
405
    printf( "Launching startup function...\n" );
406
    res = interpret(startup_func);
407
    if (res.type == F_ERROR)
408
      die( "Startup function resulted in error." );
409
    printf( "done\n" );
410
  }
411
}