]> git.ipfire.org Git - thirdparty/bird.git/blob - filter/f-util.c
A couple of filter tweaks:
[thirdparty/bird.git] / filter / f-util.c
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 *autoexec_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
43 static struct f_val
44 interpret(struct f_inst *what)
45 {
46 struct symbol *sym;
47 struct f_val v1, v2, res;
48
49 res.type = T_VOID;
50 if (!what)
51 return res;
52
53 switch(what->code) {
54 case ',':
55 TWOARGS;
56 break;
57 case '+':
58 TWOARGS;
59 if (v1.type != v2.type)
60 runtime( "Can not operate with values of incompatible types" );
61
62 switch (res.type = v1.type) {
63 case T_VOID: runtime( "Can not operate with values of type void" );
64 case T_INT: res.val.i = v1.val.i + v2.val.i; break;
65 default: runtime( "Usage of unknown type" );
66 }
67 break;
68 case '=':
69 ARG(v2, arg2);
70 sym = what->arg1;
71 switch (res.type = v2.type) {
72 case T_VOID: runtime( "Can not assign void values" );
73 case T_INT:
74 if (sym->class != SYM_VARIABLE_INT)
75 runtime( "Variable of bad type" );
76 sym->aux = v2.val.i;
77 break;
78 }
79 break;
80 case 'c':
81 res.type = T_INT;
82 res.val.i = (int) what->arg1;
83 break;
84 case 'i':
85 res.type = T_INT;
86 res.val.i = * ((int *) what->arg1);
87 break;
88 case 'p':
89 ONEARG;
90 printf( "Printing: " );
91 switch (v1.type) {
92 case T_VOID: printf( "(void)" ); break;
93 case T_INT: printf( "%d", v1.val.i ); break;
94 default: runtime( "Print of variable of unknown type" );
95 }
96 printf( "\n" );
97 break;
98 case '?':
99 ONEARG;
100 if (v1.type != T_INT)
101 runtime( "If requires integer expression" );
102 if (v1.val.i) {
103 ARG(res,arg2);
104 }
105 break;
106 case 'D':
107 printf( "DEBUGGING PRINT\n" );
108 break;
109 case '0':
110 printf( "No operation\n" );
111 break;
112 case 'd':
113 printf( "Puts: %s\n", (char *) what->arg1 );
114 break;
115 case '!':
116 switch ((int) what->arg1) {
117 case F_QUITBIRD:
118 die( "Filter asked me to die" );
119 case F_ACCEPT:
120 /* Should take care about turning ACCEPT into MODIFY */
121 case F_ERROR:
122 case F_REJECT:
123 res.type = T_RETURN;
124 res.val.i = (int) what->arg1;
125 break;
126 default:
127 bug( "unknown return type: can not happen");
128 }
129 break;
130 default:
131 bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
132 }
133 if (what->next)
134 return interpret(what->next);
135 return res;
136 }
137
138 struct f_inst *
139 f_new_inst(void)
140 {
141 struct f_inst * ret;
142 ret = cfg_alloc(sizeof(struct f_inst));
143 ret->code = 0;
144 ret->arg1 = ret->arg2 = ret->next = NULL;
145 return ret;
146 }
147
148 int
149 f_run(struct filter *filter, struct rte *rtein, struct rte **rteout)
150 {
151 struct f_inst *inst;
152 struct f_val res;
153 debug( "Running filter `%s'...", filter->name );
154
155 inst = filter->root;
156 res = interpret(inst);
157 if (res.type != T_RETURN)
158 return F_ERROR;
159 debug( "done (%d)\n", res.val.i );
160 return res.val.i;
161 }
162
163 void
164 filters_postconfig(void)
165 {
166 if (autoexec_func)
167 interpret(autoexec_func);
168 }