Statistics
| Branch: | Revision:

iof-bird-daemon / filter / filter.c @ 23b1539b

History | View | Annotate | Download (4.96 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
#include <stdio.h>
10
#include <fcntl.h>
11
#include <unistd.h>
12
#include <sys/signal.h>
13
#include <setjmp.h>
14

    
15
#include "nest/bird.h"
16
#include "lib/lists.h"
17
#include "lib/resource.h"
18
#include "lib/socket.h"
19
#include "nest/route.h"
20
#include "nest/protocol.h"
21
#include "nest/iface.h"
22
#include "conf/conf.h"
23
#include "filter/filter.h"
24

    
25
struct f_inst *startup_func = NULL;
26

    
27
#define runtime(x) do { \
28
    log( L_ERR x ); \
29
    res.type = T_RETURN; \
30
    res.val.i = F_ERROR; \
31
    return res; \
32
  } while(0)
33

    
34
#define ARG(x,y) \
35
        x = interpret(what->y); \
36
        if (x.type == T_RETURN) \
37
                return x;
38

    
39
#define ONEARG ARG(v1, arg1)
40
#define TWOARGS ARG(v1, arg1) \
41
                ARG(v2, arg2)
42
#define TWOARGS_C TWOARGS \
43
                  if (v1.type != v2.type) \
44
                    runtime( "Can not operate with values of incompatible types" );
45

    
46
static struct f_val
47
interpret(struct f_inst *what)
48
{
49
  struct symbol *sym;
50
  struct f_val v1, v2, res;
51

    
52
  res.type = T_VOID;
53
  if (!what)
54
    return res;
55

    
56
  switch(what->code) {
57
  case ',':
58
    TWOARGS;
59
    break;
60

    
61
/* Binary operators */
62
  case '+':
63
    TWOARGS_C;
64
    switch (res.type = v1.type) {
65
    case T_VOID: runtime( "Can not operate with values of type void" );
66
    case T_INT: res.val.i = v1.val.i + v2.val.i; break;
67
    default: runtime( "Usage of unknown type" );
68
    }
69
    break;
70
  case '/':
71
    TWOARGS_C;
72
    switch (res.type = v1.type) {
73
    case T_VOID: runtime( "Can not operate with values of type void" );
74
    case T_INT: res.val.i = v1.val.i / v2.val.i; break;
75
    case T_IP: if (v2.type != T_INT)
76
                 runtime( "Operator / is <ip>/<int>" );
77
               break;
78
    default: runtime( "Usage of unknown type" );
79
    }
80
    break;
81

    
82
/* Relational operators */
83
  case '!=':
84
  case '==':
85
    TWOARGS_C;
86
    res.type = T_BOOL;
87
    switch (v1.type) {
88
    case T_VOID: runtime( "Can not operate with values of type void" );
89
    case T_INT: res.val.i = (v1.val.i == v2.val.i); break;
90
    default: runtime( "Usage of unknown type" );
91
    }
92
    if (what->code == '!=')
93
      res.val.i = !(res.val.i);
94
    break;
95
  case '<':
96
    TWOARGS_C;
97
    res.type = T_BOOL;
98
    switch (v1.type) {
99
    case T_VOID: runtime( "Can not operate with values of type void" );
100
    case T_INT: res.val.i = (v1.val.i < v2.val.i); break;
101
    default: runtime( "Usage of unknown type" );
102
    }
103
    break;
104
  case '<=':
105
    TWOARGS_C;
106
    res.type = T_BOOL;
107
    switch (v1.type) {
108
    case T_VOID: runtime( "Can not operate with values of type void" );
109
    case T_INT: res.val.i = (v1.val.i <= v2.val.i); break;
110
    default: runtime( "Usage of unknown type" );
111
    }
112
    break;
113

    
114
/* Set */
115
  case 's':
116
    ARG(v2, arg2);
117
    sym = what->arg1;
118
    switch (res.type = v2.type) {
119
    case T_VOID: runtime( "Can not assign void values" );
120
    case T_INT: 
121
      if (sym->class != (SYM_VARIABLE | T_INT))
122
        runtime( "Variable of bad type" );
123
      sym->aux = v2.val.i; 
124
      break;
125
    }
126
    break;
127

    
128
  case 'c':
129
    res.type = (int) what->arg1;
130
    res.val.i = (int) what->arg2;
131
    break;
132
  case 'i':
133
    res.type = (int) what->arg1;
134
    res.val.i = * ((int *) what->arg2);
135
    break;
136
  case 'p':
137
    ONEARG;
138
    switch (v1.type) {
139
    case T_VOID: printf( "(void)" ); break;
140
    case T_INT: printf( "%d ", v1.val.i ); break;
141
    case T_STRING: printf( "%s", v1.val.i ); break;
142
    default: runtime( "Print of variable of unknown type" );
143
    }
144
    break;
145
  case '?':        /* ? has really strange error value, so we can implement if ... else nicely :-) */
146
    ONEARG;
147
    if (v1.type != T_BOOL)
148
      runtime( "If requires bool expression" );
149
    if (v1.val.i) {
150
      ARG(res,arg2);
151
      res.val.i = 0;
152
    } else res.val.i = 1;
153
    res.type = T_BOOL;
154
    break;
155
  case '0':
156
    printf( "No operation\n" );
157
    break;
158
  case 'p,':
159
    ONEARG;
160
    printf( "\n" );
161

    
162
    switch ((int) what->arg2) {
163
    case F_QUITBIRD:
164
      die( "Filter asked me to die" );
165
    case F_ACCEPT:
166
      /* Should take care about turning ACCEPT into MODIFY */
167
    case F_ERROR:
168
    case F_REJECT:
169
      res.type = T_RETURN;
170
      res.val.i = (int) what->arg1;
171
      break;
172
    case F_NOP:
173
      break;
174
    default:
175
      bug( "unknown return type: can not happen");
176
    }
177
    break;
178
  default:
179
    bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
180
  }
181
  if (what->next)
182
    return interpret(what->next);
183
  return res;
184
}
185

    
186
int
187
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool)
188
{
189
  struct f_inst *inst;
190
  struct f_val res;
191
  debug( "Running filter `%s'...", filter->name );
192

    
193
  inst = filter->root;
194
  res = interpret(inst);
195
  if (res.type != T_RETURN)
196
    return F_ERROR;
197
  debug( "done (%d)\n", res.val.i );
198
  return res.val.i;
199
}
200

    
201

    
202
void
203
filters_postconfig(void)
204
{
205
  struct f_val res;
206
  printf( "Launching startup function...\n" );
207
  if (startup_func)
208
    res = interpret(startup_func);
209
  if (res.type = F_ERROR)
210
    die( "Startup function resulted in error." );
211
  printf( "done\n" );
212
}