Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (9.9 KB)

1 23b1539b Pavel Machek
/*
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 29818140 Pavel Machek
 *
8 720d911d Pavel Machek
 *         Notice that pair is stored as integer: first << 16 | second
9 2f702671 Pavel Machek
 *
10
 *        FIXME: Check if prefixes are really prefixes.
11 23b1539b Pavel Machek
 */
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 38506f71 Pavel Machek
#include "lib/string.h"
24 23b1539b Pavel Machek
#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 2db3b288 Pavel Machek
#define ONEARG ARG(v1, a1.p)
45
#define TWOARGS ARG(v1, a1.p) \
46
                ARG(v2, a2.p)
47 23b1539b Pavel Machek
#define TWOARGS_C TWOARGS \
48
                  if (v1.type != v2.type) \
49
                    runtime( "Can not operate with values of incompatible types" );
50
51 38506f71 Pavel Machek
#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 41be4444 Pavel Machek
  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 7db7b7db Pavel Machek
  if (v1.type != v2.type)
65
    return CMP_ERROR;
66 38506f71 Pavel Machek
  switch (v1.type) {
67 f4536657 Pavel Machek
  case T_ENUM:
68 38506f71 Pavel Machek
  case T_INT: 
69 d3dd620b Pavel Machek
  case T_PAIR:
70 38506f71 Pavel Machek
    if (v1.val.i == v2.val.i) return 0;
71
    if (v1.val.i < v2.val.i) return -1;
72
    return 1;
73 43fc099b Pavel Machek
  case T_IP:
74 6dc7a0cb Pavel Machek
  case T_PREFIX:
75
    return ipa_compare(v1.val.px.ip, v2.val.px.ip);
76 41be4444 Pavel Machek
  default: { printf( "Error comparing\n" ); return CMP_ERROR; }
77 38506f71 Pavel Machek
  }
78
}
79
80 6dc7a0cb Pavel Machek
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 7db7b7db Pavel Machek
int
107
val_in_range(struct f_val v1, struct f_val v2)
108
{
109 6dc7a0cb Pavel Machek
  int res;
110
111
  res = val_simple_in_range(v1, v2);
112
113
  if (res != CMP_ERROR)
114
    return res;
115
116 2f702671 Pavel Machek
  if (((v1.type == T_INT) || ((v1.type == T_IP) || (v1.type == T_PREFIX)) && (v2.type == T_SET))) {
117 6dc7a0cb Pavel Machek
    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 7db7b7db Pavel Machek
  return CMP_ERROR;
124
}
125
126 38506f71 Pavel Machek
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 6dc7a0cb Pavel Machek
  case T_IP: PRINTF( "%I", v.val.px.ip ); break;
152 720d911d Pavel Machek
  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 38506f71 Pavel Machek
  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 36bbfc70 Pavel Machek
static struct rte **f_rte;
161
162 7db7b7db Pavel Machek
static struct f_val interpret(struct f_inst *what);
163
164
static struct f_val
165 23b1539b Pavel Machek
interpret(struct f_inst *what)
166
{
167
  struct symbol *sym;
168
  struct f_val v1, v2, res;
169 38506f71 Pavel Machek
  int i,j,k;
170 23b1539b Pavel Machek
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 38506f71 Pavel Machek
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 23b1539b Pavel Machek
    break;
211 38506f71 Pavel Machek
212
  case '!=': COMPARE(i!=0);
213
  case '==': COMPARE(i==0);
214
  case '<': COMPARE(i==-1);
215
  case '<=': COMPARE(i!=1);
216
217 29818140 Pavel Machek
    /* FIXME: Should be able to work with prefixes of limited sizes */
218 38506f71 Pavel Machek
  case '~':
219
    TWOARGS;
220 23b1539b Pavel Machek
    res.type = T_BOOL;
221 7db7b7db Pavel Machek
    res.val.i = val_in_range(v1, v2);
222
    if (res.val.i == CMP_ERROR)
223
      runtime( "~ applied on unknown type pair" );
224 23b1539b Pavel Machek
    break;
225 f4536657 Pavel Machek
  case 'de':
226
    ONEARG;
227
    res.type = T_BOOL;
228
    res.val.i = (v1.type != T_VOID);
229
    break;
230 23b1539b Pavel Machek
231 d3dd620b Pavel Machek
  /* Set to indirect value, a1 = variable, a2 = value */
232 23b1539b Pavel Machek
  case 's':
233 2db3b288 Pavel Machek
    ARG(v2, a2.p);
234
    sym = what->a1.p;
235 23b1539b Pavel Machek
    switch (res.type = v2.type) {
236
    case T_VOID: runtime( "Can not assign void values" );
237 f4536657 Pavel Machek
    case T_ENUM:
238 23b1539b Pavel Machek
    case T_INT: 
239 d3dd620b Pavel Machek
    case T_IP: 
240
    case T_PREFIX: 
241
    case T_PAIR: 
242
      if (sym->class != (SYM_VARIABLE | v2.type))
243 23b1539b Pavel Machek
        runtime( "Variable of bad type" );
244 d3dd620b Pavel Machek
      * (struct f_val *) sym->aux2 = v2; 
245 23b1539b Pavel Machek
      break;
246 d3dd620b Pavel Machek
    default:
247
      bug( "Set to invalid type\n" );
248 23b1539b Pavel Machek
    }
249
    break;
250
251 d3dd620b Pavel Machek
  case 'c':        /* integer (or simple type) constant */
252 2db3b288 Pavel Machek
    res.type = what->a1.i;
253 d3dd620b Pavel Machek
    res.val.i = what->a2.i;
254 23b1539b Pavel Machek
    break;
255 38506f71 Pavel Machek
  case 'C':
256
    res = * ((struct f_val *) what->a1.p);
257
    break;
258 23b1539b Pavel Machek
  case 'p':
259
    ONEARG;
260 38506f71 Pavel Machek
    val_print(v1);
261 23b1539b Pavel Machek
    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 2db3b288 Pavel Machek
      ARG(res,a2.p);
268 23b1539b Pavel Machek
      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 d3dd620b Pavel Machek
    if (what->a2.i != F_NONL)
278
      printf( "\n" );
279 23b1539b Pavel Machek
280 2db3b288 Pavel Machek
    switch (what->a2.i) {
281 23b1539b Pavel Machek
    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 2db3b288 Pavel Machek
      res.val.i = what->a1.i;
289 23b1539b Pavel Machek
      break;
290 d3dd620b Pavel Machek
    case F_NONL:
291 23b1539b Pavel Machek
    case F_NOP:
292
      break;
293
    default:
294
      bug( "unknown return type: can not happen");
295
    }
296
    break;
297 36bbfc70 Pavel Machek
  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 6dc7a0cb Pavel Machek
        res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
304 36bbfc70 Pavel Machek
        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 6dc7a0cb Pavel Machek
  case 'ea':        /* Access to extended attributes [hmm, but we need it read/write, do we?] */
317 91447965 Pavel Machek
    {
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 6dc7a0cb Pavel Machek
    break;
331 36bbfc70 Pavel Machek
  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 6dc7a0cb Pavel Machek
    case T_IP: res.val.px.ip = v1.val.px.ip; break;
339 36bbfc70 Pavel Machek
    default: bug( "Unknown prefix to conversion\n" );
340
    }
341
    break;
342 6542ece9 Pavel Machek
  case 'ca': /* CALL */
343
    ONEARG;
344
    res = interpret(what->a2.p);
345
    break;
346 41be4444 Pavel Machek
  case 'SW':
347 7db7b7db Pavel Machek
    ONEARG;
348 41be4444 Pavel Machek
    {
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 7db7b7db Pavel Machek
    break;
363 d3dd620b Pavel Machek
  case 'iM': /* IP.MASK(val) */
364 f4536657 Pavel Machek
    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 d3dd620b Pavel Machek
    break;
375 23b1539b Pavel Machek
  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 36bbfc70 Pavel Machek
  f_rte = rte;
391 23b1539b Pavel Machek
  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 8ba2cc06 Pavel Machek
  if (startup_func) {
405
    printf( "Launching startup function...\n" );
406 23b1539b Pavel Machek
    res = interpret(startup_func);
407 bad631e0 Pavel Machek
    if (res.type == F_ERROR)
408 8ba2cc06 Pavel Machek
      die( "Startup function resulted in error." );
409
    printf( "done\n" );
410
  }
411 23b1539b Pavel Machek
}