]> git.ipfire.org Git - thirdparty/bird.git/blob - filter/filter.c
Implements 'allow local as' option.
[thirdparty/bird.git] / filter / filter.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
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, int l)
55 {
56 struct adata *res = lp_alloc(pool, sizeof(struct adata) + l);
57 res->length = l;
58 return res;
59 }
60
61 static void
62 pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
63 {
64 byte *end = buf + size - 16;
65
66 while (p)
67 {
68 if (buf > end)
69 {
70 strcpy(buf, " ...");
71 return;
72 }
73
74 switch(p->kind)
75 {
76 case PM_ASN:
77 buf += bsprintf(buf, " %u", p->val);
78 break;
79
80 case PM_QUESTION:
81 buf += bsprintf(buf, " ?");
82 break;
83
84 case PM_ASTERISK:
85 buf += bsprintf(buf, " *");
86 break;
87
88 case PM_ASN_EXPR:
89 buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val));
90 break;
91 }
92
93 p = p->next;
94 }
95
96 *buf = 0;
97 }
98
99 static inline int
100 int_cmp(int i1, int i2)
101 {
102 return (i1 > i2) - (i1 < i2);
103 }
104
105 static inline int
106 uint_cmp(unsigned int i1, unsigned int i2)
107 {
108 return (int)(i1 > i2) - (int)(i1 < i2);
109 }
110
111 static inline int
112 u64_cmp(u64 i1, u64 i2)
113 {
114 return (int)(i1 > i2) - (int)(i1 < i2);
115 }
116
117 /**
118 * val_compare - compare two values
119 * @v1: first value
120 * @v2: second value
121 *
122 * Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
123 * error. Tree module relies on this giving consistent results so
124 * that it can be used for building balanced trees.
125 */
126 int
127 val_compare(struct f_val v1, struct f_val v2)
128 {
129 int rc;
130
131 if (v1.type != v2.type) {
132 if (v1.type == T_VOID) /* Hack for else */
133 return -1;
134 if (v2.type == T_VOID)
135 return 1;
136
137 #ifndef IPV6
138 /* IP->Quad implicit conversion */
139 if ((v1.type == T_QUAD) && (v2.type == T_IP))
140 return uint_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
141 if ((v1.type == T_IP) && (v2.type == T_QUAD))
142 return uint_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
143 #endif
144
145 debug( "Types do not match in val_compare\n" );
146 return CMP_ERROR;
147 }
148
149 switch (v1.type) {
150 case T_VOID:
151 return 0;
152 case T_ENUM:
153 case T_INT:
154 case T_BOOL:
155 return int_cmp(v1.val.i, v2.val.i);
156 case T_PAIR:
157 case T_QUAD:
158 return uint_cmp(v1.val.i, v2.val.i);
159 case T_EC:
160 return u64_cmp(v1.val.ec, v2.val.ec);
161 case T_IP:
162 return ipa_compare(v1.val.px.ip, v2.val.px.ip);
163 case T_PREFIX:
164 if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
165 return rc;
166 return int_cmp(v1.val.px.len, v2.val.px.len);
167 case T_STRING:
168 return strcmp(v1.val.s, v2.val.s);
169 default:
170 return CMP_ERROR;
171 }
172 }
173
174 static int
175 pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2)
176 {
177 while (m1 && m2)
178 {
179 if ((m1->kind != m2->kind) || (m1->val != m2->val))
180 return 0;
181
182 m1 = m1->next;
183 m2 = m2->next;
184 }
185
186 return !m1 && !m2;
187 }
188
189 /**
190 * val_same - compare two values
191 * @v1: first value
192 * @v2: second value
193 *
194 * Compares two values and returns 1 if they are same and 0 if not.
195 * Comparison of values of different types is valid and returns 0.
196 */
197 int
198 val_same(struct f_val v1, struct f_val v2)
199 {
200 int rc;
201
202 rc = val_compare(v1, v2);
203 if (rc != CMP_ERROR)
204 return !rc;
205
206 if (v1.type != v2.type)
207 return 0;
208
209 switch (v1.type) {
210 case T_PATH_MASK:
211 return pm_path_same(v1.val.path_mask, v2.val.path_mask);
212 case T_PATH:
213 case T_CLIST:
214 case T_ECLIST:
215 return adata_same(v1.val.ad, v2.val.ad);
216 case T_SET:
217 return same_tree(v1.val.t, v2.val.t);
218 case T_PREFIX_SET:
219 return trie_same(v1.val.ti, v2.val.ti);
220 default:
221 bug("Invalid type in val_same(): %x", v1.type);
222 }
223 }
224
225 void
226 fprefix_get_bounds(struct f_prefix *px, int *l, int *h)
227 {
228 *l = *h = px->len & LEN_MASK;
229
230 if (px->len & LEN_MINUS)
231 *l = 0;
232
233 else if (px->len & LEN_PLUS)
234 *h = MAX_PREFIX_LENGTH;
235
236 else if (px->len & LEN_RANGE)
237 {
238 *l = 0xff & (px->len >> 16);
239 *h = 0xff & (px->len >> 8);
240 }
241 }
242
243 static int
244 clist_set_type(struct f_tree *set, struct f_val *v)
245 {
246 switch (set->from.type) {
247 case T_PAIR:
248 v->type = T_PAIR;
249 return 1;
250 case T_QUAD:
251 #ifndef IPV6
252 case T_IP:
253 #endif
254 v->type = T_QUAD;
255 return 1;
256 break;
257 default:
258 v->type = T_VOID;
259 return 0;
260 }
261 }
262
263 static inline int
264 eclist_set_type(struct f_tree *set)
265 { return set->from.type == T_EC; }
266
267 static int
268 clist_match_set(struct adata *clist, struct f_tree *set)
269 {
270 if (!clist)
271 return 0;
272
273 struct f_val v;
274 if (!clist_set_type(set, &v))
275 return CMP_ERROR;
276
277 u32 *l = (u32 *) clist->data;
278 u32 *end = l + clist->length/4;
279
280 while (l < end) {
281 v.val.i = *l++;
282 if (find_tree(set, v))
283 return 1;
284 }
285 return 0;
286 }
287
288 static int
289 eclist_match_set(struct adata *list, struct f_tree *set)
290 {
291 if (!list)
292 return 0;
293
294 if (!eclist_set_type(set))
295 return CMP_ERROR;
296
297 struct f_val v;
298 u32 *l = int_set_get_data(list);
299 int len = int_set_get_size(list);
300 int i;
301
302 v.type = T_EC;
303 for (i = 0; i < len; i += 2) {
304 v.val.ec = ec_get(l, i);
305 if (find_tree(set, v))
306 return 1;
307 }
308
309 return 0;
310 }
311
312 static struct adata *
313 clist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
314 {
315 if (!list)
316 return NULL;
317
318 int tree = (set.type == T_SET); /* 1 -> set is T_SET, 0 -> set is T_CLIST */
319 struct f_val v;
320 if (tree)
321 clist_set_type(set.val.t, &v);
322 else
323 v.type = T_PAIR;
324
325 int len = int_set_get_size(list);
326 u32 *l = int_set_get_data(list);
327 u32 tmp[len];
328 u32 *k = tmp;
329 u32 *end = l + len;
330
331 while (l < end) {
332 v.val.i = *l++;
333 /* pos && member(val, set) || !pos && !member(val, set), member() depends on tree */
334 if ((tree ? !!find_tree(set.val.t, v) : int_set_contains(set.val.ad, v.val.i)) == pos)
335 *k++ = v.val.i;
336 }
337
338 int nl = (k - tmp) * 4;
339 if (nl == list->length)
340 return list;
341
342 struct adata *res = adata_empty(pool, nl);
343 memcpy(res->data, tmp, nl);
344 return res;
345 }
346
347 static struct adata *
348 eclist_filter(struct linpool *pool, struct adata *list, struct f_val set, int pos)
349 {
350 if (!list)
351 return NULL;
352
353 int tree = (set.type == T_SET); /* 1 -> set is T_SET, 0 -> set is T_CLIST */
354 struct f_val v;
355
356 int len = int_set_get_size(list);
357 u32 *l = int_set_get_data(list);
358 u32 tmp[len];
359 u32 *k = tmp;
360 int i;
361
362 v.type = T_EC;
363 for (i = 0; i < len; i += 2) {
364 v.val.ec = ec_get(l, i);
365 /* pos && member(val, set) || !pos && !member(val, set), member() depends on tree */
366 if ((tree ? !!find_tree(set.val.t, v) : ec_set_contains(set.val.ad, v.val.ec)) == pos) {
367 *k++ = l[i];
368 *k++ = l[i+1];
369 }
370 }
371
372 int nl = (k - tmp) * 4;
373 if (nl == list->length)
374 return list;
375
376 struct adata *res = adata_empty(pool, nl);
377 memcpy(res->data, tmp, nl);
378 return res;
379 }
380
381 /**
382 * val_in_range - implement |~| operator
383 * @v1: element
384 * @v2: set
385 *
386 * Checks if @v1 is element (|~| operator) of @v2.
387 */
388 static int
389 val_in_range(struct f_val v1, struct f_val v2)
390 {
391 if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
392 return as_path_match(v1.val.ad, v2.val.path_mask);
393
394 if ((v1.type == T_INT) && (v2.type == T_PATH))
395 return as_path_contains(v2.val.ad, v1.val.i, 1);
396
397 if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
398 return int_set_contains(v2.val.ad, v1.val.i);
399 #ifndef IPV6
400 /* IP->Quad implicit conversion */
401 if ((v1.type == T_IP) && (v2.type == T_CLIST))
402 return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
403 #endif
404
405 if ((v1.type == T_EC) && (v2.type == T_ECLIST))
406 return ec_set_contains(v2.val.ad, v1.val.ec);
407
408 if ((v1.type == T_STRING) && (v2.type == T_STRING))
409 return patmatch(v2.val.s, v1.val.s);
410
411 if ((v1.type == T_IP) && (v2.type == T_PREFIX))
412 return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
413
414 if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX))
415 return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
416
417 if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX_SET))
418 return trie_match_fprefix(v2.val.ti, &v1.val.px);
419
420 if (v2.type != T_SET)
421 return CMP_ERROR;
422
423 /* With integrated Quad<->IP implicit conversion */
424 if ((v1.type == v2.val.t->from.type) ||
425 ((IP_VERSION == 4) && (v1.type == T_QUAD) && (v2.val.t->from.type == T_IP)))
426 return !!find_tree(v2.val.t, v1);
427
428 if (v1.type == T_CLIST)
429 return clist_match_set(v1.val.ad, v2.val.t);
430
431 if (v1.type == T_ECLIST)
432 return eclist_match_set(v1.val.ad, v2.val.t);
433
434 if (v1.type == T_PATH)
435 return as_path_match_set(v1.val.ad, v2.val.t);
436
437 return CMP_ERROR;
438 }
439
440 static void
441 tree_node_print(struct f_tree *t, char **sep)
442 {
443 if (t == NULL)
444 return;
445
446 tree_node_print(t->left, sep);
447
448 logn(*sep);
449 val_print(t->from);
450 if (val_compare(t->from, t->to) != 0)
451 {
452 logn( ".." );
453 val_print(t->to);
454 }
455 *sep = ", ";
456
457 tree_node_print(t->right, sep);
458 }
459
460 static void
461 tree_print(struct f_tree *t)
462 {
463 char *sep = "";
464 logn( "[" );
465 tree_node_print(t, &sep);
466 logn( "] " );
467 }
468
469 /*
470 * val_print - format filter value
471 */
472 void
473 val_print(struct f_val v)
474 {
475 char buf2[1024];
476 switch (v.type) {
477 case T_VOID: logn("(void)"); return;
478 case T_BOOL: logn(v.val.i ? "TRUE" : "FALSE"); return;
479 case T_INT: logn("%d", v.val.i); return;
480 case T_STRING: logn("%s", v.val.s); return;
481 case T_IP: logn("%I", v.val.px.ip); return;
482 case T_PREFIX: logn("%I/%d", v.val.px.ip, v.val.px.len); return;
483 case T_PAIR: logn("(%d,%d)", v.val.i >> 16, v.val.i & 0xffff); return;
484 case T_QUAD: logn("%R", v.val.i); return;
485 case T_EC: ec_format(buf2, v.val.ec); logn("%s", buf2); return;
486 case T_PREFIX_SET: trie_print(v.val.ti); return;
487 case T_SET: tree_print(v.val.t); return;
488 case T_ENUM: logn("(enum %x)%d", v.type, v.val.i); return;
489 case T_PATH: as_path_format(v.val.ad, buf2, 1000); logn("(path %s)", buf2); return;
490 case T_CLIST: int_set_format(v.val.ad, 1, -1, buf2, 1000); logn("(clist %s)", buf2); return;
491 case T_ECLIST: ec_set_format(v.val.ad, -1, buf2, 1000); logn("(eclist %s)", buf2); return;
492 case T_PATH_MASK: pm_format(v.val.path_mask, buf2, 1000); logn("(pathmask%s)", buf2); return;
493 default: logn( "[unknown type %x]", v.type ); return;
494 }
495 }
496
497 static struct rte **f_rte;
498 static struct rta *f_old_rta;
499 static struct ea_list **f_tmp_attrs;
500 static struct linpool *f_pool;
501 static int f_flags;
502
503 static inline void f_rte_cow(void)
504 {
505 *f_rte = rte_cow(*f_rte);
506 }
507
508 /*
509 * rta_cow - prepare rta for modification by filter
510 */
511 static void
512 f_rta_cow(void)
513 {
514 if ((*f_rte)->attrs->aflags & RTAF_CACHED) {
515
516 /* Prepare to modify rte */
517 f_rte_cow();
518
519 /* Store old rta to free it later */
520 f_old_rta = (*f_rte)->attrs;
521
522 /*
523 * Alloc new rta, do shallow copy and update rte. Fields eattrs
524 * and nexthops of rta are shared with f_old_rta (they will be
525 * copied when the cached rta will be obtained at the end of
526 * f_run()), also the lock of hostentry is inherited (we suppose
527 * hostentry is not changed by filters).
528 */
529 rta *ra = lp_alloc(f_pool, sizeof(rta));
530 memcpy(ra, f_old_rta, sizeof(rta));
531 ra->aflags = 0;
532 (*f_rte)->attrs = ra;
533 }
534 }
535
536 static struct rate_limit rl_runtime_err;
537
538 #define runtime(x) do { \
539 log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
540 res.type = T_RETURN; \
541 res.val.i = F_ERROR; \
542 return res; \
543 } while(0)
544
545 #define ARG(x,y) \
546 x = interpret(what->y); \
547 if (x.type & T_RETURN) \
548 return x;
549
550 #define ONEARG ARG(v1, a1.p)
551 #define TWOARGS ARG(v1, a1.p) \
552 ARG(v2, a2.p)
553 #define TWOARGS_C TWOARGS \
554 if (v1.type != v2.type) \
555 runtime( "Can't operate with values of incompatible types" );
556 #define ACCESS_RTE \
557 do { if (!f_rte) runtime("No route to access"); } while (0)
558
559 /**
560 * interpret
561 * @what: filter to interpret
562 *
563 * Interpret given tree of filter instructions. This is core function
564 * of filter system and does all the hard work.
565 *
566 * Each instruction has 4 fields: code (which is instruction code),
567 * aux (which is extension to instruction code, typically type),
568 * arg1 and arg2 - arguments. Depending on instruction, arguments
569 * are either integers, or pointers to instruction trees. Common
570 * instructions like +, that have two expressions as arguments use
571 * TWOARGS macro to get both of them evaluated.
572 *
573 * &f_val structures are copied around, so there are no problems with
574 * memory managment.
575 */
576 static struct f_val
577 interpret(struct f_inst *what)
578 {
579 struct symbol *sym;
580 struct f_val v1, v2, res, *vp;
581 unsigned u1, u2;
582 int i;
583 u32 as;
584
585 res.type = T_VOID;
586 if (!what)
587 return res;
588
589 switch(what->code) {
590 case ',':
591 TWOARGS;
592 break;
593
594 /* Binary operators */
595 case '+':
596 TWOARGS_C;
597 switch (res.type = v1.type) {
598 case T_VOID: runtime( "Can't operate with values of type void" );
599 case T_INT: res.val.i = v1.val.i + v2.val.i; break;
600 default: runtime( "Usage of unknown type" );
601 }
602 break;
603 case '-':
604 TWOARGS_C;
605 switch (res.type = v1.type) {
606 case T_VOID: runtime( "Can't operate with values of type void" );
607 case T_INT: res.val.i = v1.val.i - v2.val.i; break;
608 default: runtime( "Usage of unknown type" );
609 }
610 break;
611 case '*':
612 TWOARGS_C;
613 switch (res.type = v1.type) {
614 case T_VOID: runtime( "Can't operate with values of type void" );
615 case T_INT: res.val.i = v1.val.i * v2.val.i; break;
616 default: runtime( "Usage of unknown type" );
617 }
618 break;
619 case '/':
620 TWOARGS_C;
621 switch (res.type = v1.type) {
622 case T_VOID: runtime( "Can't operate with values of type void" );
623 case T_INT: if (v2.val.i == 0) runtime( "Mother told me not to divide by 0" );
624 res.val.i = v1.val.i / v2.val.i; break;
625 default: runtime( "Usage of unknown type" );
626 }
627 break;
628
629 case '&':
630 case '|':
631 ARG(v1, a1.p);
632 if (v1.type != T_BOOL)
633 runtime( "Can't do boolean operation on non-booleans" );
634 if (v1.val.i == (what->code == '|')) {
635 res.type = T_BOOL;
636 res.val.i = v1.val.i;
637 break;
638 }
639
640 ARG(v2, a2.p);
641 if (v2.type != T_BOOL)
642 runtime( "Can't do boolean operation on non-booleans" );
643 res.type = T_BOOL;
644 res.val.i = v2.val.i;
645 break;
646
647 case P('m','p'):
648 TWOARGS;
649 if ((v1.type != T_INT) || (v2.type != T_INT))
650 runtime( "Can't operate with value of non-integer type in pair constructor" );
651 u1 = v1.val.i;
652 u2 = v2.val.i;
653 if ((u1 > 0xFFFF) || (u2 > 0xFFFF))
654 runtime( "Can't operate with value out of bounds in pair constructor" );
655 res.val.i = (u1 << 16) | u2;
656 res.type = T_PAIR;
657 break;
658
659 case P('m','c'):
660 {
661 TWOARGS;
662
663 int check, ipv4_used;
664 u32 key, val;
665
666 if (v1.type == T_INT) {
667 ipv4_used = 0; key = v1.val.i;
668 }
669 else if (v1.type == T_QUAD) {
670 ipv4_used = 1; key = v1.val.i;
671 }
672 #ifndef IPV6
673 /* IP->Quad implicit conversion */
674 else if (v1.type == T_IP) {
675 ipv4_used = 1; key = ipa_to_u32(v1.val.px.ip);
676 }
677 #endif
678 else
679 runtime("Can't operate with key of non-integer/IPv4 type in EC constructor");
680
681 if (v2.type != T_INT)
682 runtime("Can't operate with value of non-integer type in EC constructor");
683 val = v2.val.i;
684
685 res.type = T_EC;
686
687 if (what->aux == EC_GENERIC) {
688 check = 0; res.val.ec = ec_generic(key, val);
689 }
690 else if (ipv4_used) {
691 check = 1; res.val.ec = ec_ip4(what->aux, key, val);
692 }
693 else if (key < 0x10000) {
694 check = 0; res.val.ec = ec_as2(what->aux, key, val);
695 }
696 else {
697 check = 1; res.val.ec = ec_as4(what->aux, key, val);
698 }
699
700 if (check && (val > 0xFFFF))
701 runtime("Can't operate with value out of bounds in EC constructor");
702
703 break;
704 }
705
706 /* Relational operators */
707
708 #define COMPARE(x) \
709 TWOARGS; \
710 i = val_compare(v1, v2); \
711 if (i==CMP_ERROR) \
712 runtime( "Can't compare values of incompatible types" ); \
713 res.type = T_BOOL; \
714 res.val.i = (x); \
715 break;
716
717 #define SAME(x) \
718 TWOARGS; \
719 i = val_same(v1, v2); \
720 res.type = T_BOOL; \
721 res.val.i = (x); \
722 break;
723
724 case P('!','='): SAME(!i);
725 case P('=','='): SAME(i);
726 case '<': COMPARE(i==-1);
727 case P('<','='): COMPARE(i!=1);
728
729 case '!':
730 ONEARG;
731 if (v1.type != T_BOOL)
732 runtime( "Not applied to non-boolean" );
733 res = v1;
734 res.val.i = !res.val.i;
735 break;
736
737 case '~':
738 TWOARGS;
739 res.type = T_BOOL;
740 res.val.i = val_in_range(v1, v2);
741 if (res.val.i == CMP_ERROR)
742 runtime( "~ applied on unknown type pair" );
743 res.val.i = !!res.val.i;
744 break;
745 case P('d','e'):
746 ONEARG;
747 res.type = T_BOOL;
748 res.val.i = (v1.type != T_VOID);
749 break;
750
751 /* Set to indirect value, a1 = variable, a2 = value */
752 case 's':
753 ARG(v2, a2.p);
754 sym = what->a1.p;
755 vp = sym->def;
756 if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
757 #ifndef IPV6
758 /* IP->Quad implicit conversion */
759 if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
760 vp->type = T_QUAD;
761 vp->val.i = ipa_to_u32(v2.val.px.ip);
762 break;
763 }
764 #endif
765 runtime( "Assigning to variable of incompatible type" );
766 }
767 *vp = v2;
768 break;
769
770 /* some constants have value in a2, some in *a1.p, strange. */
771 case 'c': /* integer (or simple type) constant, string, set, or prefix_set */
772 res.type = what->aux;
773
774 if (res.type == T_PREFIX_SET)
775 res.val.ti = what->a2.p;
776 else if (res.type == T_SET)
777 res.val.t = what->a2.p;
778 else if (res.type == T_STRING)
779 res.val.s = what->a2.p;
780 else
781 res.val.i = what->a2.i;
782 break;
783 case 'V':
784 case 'C':
785 res = * ((struct f_val *) what->a1.p);
786 break;
787 case 'p':
788 ONEARG;
789 val_print(v1);
790 break;
791 case '?': /* ? has really strange error value, so we can implement if ... else nicely :-) */
792 ONEARG;
793 if (v1.type != T_BOOL)
794 runtime( "If requires boolean expression" );
795 if (v1.val.i) {
796 ARG(res,a2.p);
797 res.val.i = 0;
798 } else res.val.i = 1;
799 res.type = T_BOOL;
800 break;
801 case '0':
802 debug( "No operation\n" );
803 break;
804 case P('p',','):
805 ONEARG;
806 if (what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p))
807 log_commit(*L_INFO);
808
809 switch (what->a2.i) {
810 case F_QUITBIRD:
811 die( "Filter asked me to die" );
812 case F_ACCEPT:
813 /* Should take care about turning ACCEPT into MODIFY */
814 case F_ERROR:
815 case F_REJECT: /* FIXME (noncritical) Should print complete route along with reason to reject route */
816 res.type = T_RETURN;
817 res.val.i = what->a2.i;
818 return res; /* We have to return now, no more processing. */
819 case F_NONL:
820 case F_NOP:
821 break;
822 default:
823 bug( "unknown return type: Can't happen");
824 }
825 break;
826 case 'a': /* rta access */
827 {
828 ACCESS_RTE;
829 struct rta *rta = (*f_rte)->attrs;
830 res.type = what->aux;
831
832 switch (what->a2.i)
833 {
834 case SA_FROM: res.val.px.ip = rta->from; break;
835 case SA_GW: res.val.px.ip = rta->gw; break;
836 case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix;
837 res.val.px.len = (*f_rte)->net->n.pxlen; break;
838 case SA_PROTO: res.val.s = rta->proto->name; break;
839 case SA_SOURCE: res.val.i = rta->source; break;
840 case SA_SCOPE: res.val.i = rta->scope; break;
841 case SA_CAST: res.val.i = rta->cast; break;
842 case SA_DEST: res.val.i = rta->dest; break;
843 case SA_IFNAME: res.val.s = rta->iface ? rta->iface->name : ""; break;
844 case SA_IFINDEX: res.val.i = rta->iface ? rta->iface->index : 0; break;
845
846 default:
847 bug("Invalid static attribute access (%x)", res.type);
848 }
849 }
850 break;
851 case P('a','S'):
852 ACCESS_RTE;
853 ONEARG;
854 if (what->aux != v1.type)
855 runtime( "Attempt to set static attribute to incompatible type" );
856
857 f_rta_cow();
858 {
859 struct rta *rta = (*f_rte)->attrs;
860
861 switch (what->a2.i)
862 {
863 case SA_FROM:
864 rta->from = v1.val.px.ip;
865 break;
866
867 case SA_GW:
868 {
869 ip_addr ip = v1.val.px.ip;
870 neighbor *n = neigh_find(rta->proto, &ip, 0);
871 if (!n || (n->scope == SCOPE_HOST))
872 runtime( "Invalid gw address" );
873
874 rta->dest = RTD_ROUTER;
875 rta->gw = ip;
876 rta->iface = n->iface;
877 rta->nexthops = NULL;
878 rta->hostentry = NULL;
879 }
880 break;
881
882 case SA_SCOPE:
883 rta->scope = v1.val.i;
884 break;
885
886 case SA_DEST:
887 i = v1.val.i;
888 if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
889 runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
890
891 rta->dest = i;
892 rta->gw = IPA_NONE;
893 rta->iface = NULL;
894 rta->nexthops = NULL;
895 rta->hostentry = NULL;
896 break;
897
898 default:
899 bug("Invalid static attribute access (%x)", res.type);
900 }
901 }
902 break;
903 case P('e','a'): /* Access to extended attributes */
904 ACCESS_RTE;
905 {
906 eattr *e = NULL;
907 if (!(f_flags & FF_FORCE_TMPATTR))
908 e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
909 if (!e)
910 e = ea_find( (*f_tmp_attrs), what->a2.i );
911 if ((!e) && (f_flags & FF_FORCE_TMPATTR))
912 e = ea_find( (*f_rte)->attrs->eattrs, what->a2.i );
913
914 if (!e) {
915 /* A special case: undefined int_set looks like empty int_set */
916 if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
917 res.type = T_CLIST;
918 res.val.ad = adata_empty(f_pool, 0);
919 break;
920 }
921 /* The same special case for ec_set */
922 else if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
923 res.type = T_ECLIST;
924 res.val.ad = adata_empty(f_pool, 0);
925 break;
926 }
927
928 /* Undefined value */
929 res.type = T_VOID;
930 break;
931 }
932
933 switch (what->aux & EAF_TYPE_MASK) {
934 case EAF_TYPE_INT:
935 res.type = T_INT;
936 res.val.i = e->u.data;
937 break;
938 case EAF_TYPE_ROUTER_ID:
939 res.type = T_QUAD;
940 res.val.i = e->u.data;
941 break;
942 case EAF_TYPE_OPAQUE:
943 res.type = T_ENUM_EMPTY;
944 res.val.i = 0;
945 break;
946 case EAF_TYPE_IP_ADDRESS:
947 res.type = T_IP;
948 struct adata * ad = e->u.ptr;
949 res.val.px.ip = * (ip_addr *) ad->data;
950 break;
951 case EAF_TYPE_AS_PATH:
952 res.type = T_PATH;
953 res.val.ad = e->u.ptr;
954 break;
955 case EAF_TYPE_INT_SET:
956 res.type = T_CLIST;
957 res.val.ad = e->u.ptr;
958 break;
959 case EAF_TYPE_EC_SET:
960 res.type = T_ECLIST;
961 res.val.ad = e->u.ptr;
962 break;
963 case EAF_TYPE_UNDEF:
964 res.type = T_VOID;
965 break;
966 default:
967 bug("Unknown type in e,a");
968 }
969 }
970 break;
971 case P('e','S'):
972 ACCESS_RTE;
973 ONEARG;
974 {
975 struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
976
977 l->next = NULL;
978 l->flags = EALF_SORTED;
979 l->count = 1;
980 l->attrs[0].id = what->a2.i;
981 l->attrs[0].flags = 0;
982 l->attrs[0].type = what->aux | EAF_ORIGINATED;
983 switch (what->aux & EAF_TYPE_MASK) {
984 case EAF_TYPE_INT:
985 if (v1.type != T_INT)
986 runtime( "Setting int attribute to non-int value" );
987 l->attrs[0].u.data = v1.val.i;
988 break;
989
990 case EAF_TYPE_ROUTER_ID:
991 #ifndef IPV6
992 /* IP->Quad implicit conversion */
993 if (v1.type == T_IP) {
994 l->attrs[0].u.data = ipa_to_u32(v1.val.px.ip);
995 break;
996 }
997 #endif
998 /* T_INT for backward compatibility */
999 if ((v1.type != T_QUAD) && (v1.type != T_INT))
1000 runtime( "Setting quad attribute to non-quad value" );
1001 l->attrs[0].u.data = v1.val.i;
1002 break;
1003
1004 case EAF_TYPE_OPAQUE:
1005 runtime( "Setting opaque attribute is not allowed" );
1006 break;
1007 case EAF_TYPE_IP_ADDRESS:
1008 if (v1.type != T_IP)
1009 runtime( "Setting ip attribute to non-ip value" );
1010 int len = sizeof(ip_addr);
1011 struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
1012 ad->length = len;
1013 (* (ip_addr *) ad->data) = v1.val.px.ip;
1014 l->attrs[0].u.ptr = ad;
1015 break;
1016 case EAF_TYPE_AS_PATH:
1017 if (v1.type != T_PATH)
1018 runtime( "Setting path attribute to non-path value" );
1019 l->attrs[0].u.ptr = v1.val.ad;
1020 break;
1021 case EAF_TYPE_INT_SET:
1022 if (v1.type != T_CLIST)
1023 runtime( "Setting clist attribute to non-clist value" );
1024 l->attrs[0].u.ptr = v1.val.ad;
1025 break;
1026 case EAF_TYPE_EC_SET:
1027 if (v1.type != T_ECLIST)
1028 runtime( "Setting eclist attribute to non-eclist value" );
1029 l->attrs[0].u.ptr = v1.val.ad;
1030 break;
1031 case EAF_TYPE_UNDEF:
1032 if (v1.type != T_VOID)
1033 runtime( "Setting void attribute to non-void value" );
1034 l->attrs[0].u.data = 0;
1035 break;
1036 default: bug("Unknown type in e,S");
1037 }
1038
1039 if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
1040 f_rta_cow();
1041 l->next = (*f_rte)->attrs->eattrs;
1042 (*f_rte)->attrs->eattrs = l;
1043 } else {
1044 l->next = (*f_tmp_attrs);
1045 (*f_tmp_attrs) = l;
1046 }
1047 }
1048 break;
1049 case 'P':
1050 ACCESS_RTE;
1051 res.type = T_INT;
1052 res.val.i = (*f_rte)->pref;
1053 break;
1054 case P('P','S'):
1055 ACCESS_RTE;
1056 ONEARG;
1057 if (v1.type != T_INT)
1058 runtime( "Can't set preference to non-integer" );
1059 if ((v1.val.i < 0) || (v1.val.i > 0xFFFF))
1060 runtime( "Setting preference value out of bounds" );
1061 f_rte_cow();
1062 (*f_rte)->pref = v1.val.i;
1063 break;
1064 case 'L': /* Get length of */
1065 ONEARG;
1066 res.type = T_INT;
1067 switch(v1.type) {
1068 case T_PREFIX: res.val.i = v1.val.px.len; break;
1069 case T_PATH: res.val.i = as_path_getlen(v1.val.ad); break;
1070 case T_CLIST: res.val.i = int_set_get_size(v1.val.ad); break;
1071 case T_ECLIST: res.val.i = ec_set_get_size(v1.val.ad); break;
1072 default: runtime( "Prefix, path, clist or eclist expected" );
1073 }
1074 break;
1075 case P('c','p'): /* Convert prefix to ... */
1076 ONEARG;
1077 if (v1.type != T_PREFIX)
1078 runtime( "Prefix expected" );
1079 res.type = what->aux;
1080 switch(res.type) {
1081 /* case T_INT: res.val.i = v1.val.px.len; break; Not needed any more */
1082 case T_IP: res.val.px.ip = v1.val.px.ip; break;
1083 default: bug( "Unknown prefix to conversion" );
1084 }
1085 break;
1086 case P('a','f'): /* Get first ASN from AS PATH */
1087 ONEARG;
1088 if (v1.type != T_PATH)
1089 runtime( "AS path expected" );
1090
1091 as = 0;
1092 as_path_get_first(v1.val.ad, &as);
1093 res.type = T_INT;
1094 res.val.i = as;
1095 break;
1096 case P('a','l'): /* Get last ASN from AS PATH */
1097 ONEARG;
1098 if (v1.type != T_PATH)
1099 runtime( "AS path expected" );
1100
1101 as = 0;
1102 as_path_get_last(v1.val.ad, &as);
1103 res.type = T_INT;
1104 res.val.i = as;
1105 break;
1106 case 'r':
1107 ONEARG;
1108 res = v1;
1109 res.type |= T_RETURN;
1110 return res;
1111 case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out */
1112 ONEARG;
1113 res = interpret(what->a2.p);
1114 if (res.type == T_RETURN)
1115 return res;
1116 res.type &= ~T_RETURN;
1117 break;
1118 case P('c','v'): /* Clear local variables */
1119 for (sym = what->a1.p; sym != NULL; sym = sym->aux2)
1120 ((struct f_val *) sym->def)->type = T_VOID;
1121 break;
1122 case P('S','W'):
1123 ONEARG;
1124 {
1125 struct f_tree *t = find_tree(what->a2.p, v1);
1126 if (!t) {
1127 v1.type = T_VOID;
1128 t = find_tree(what->a2.p, v1);
1129 if (!t) {
1130 debug( "No else statement?\n");
1131 break;
1132 }
1133 }
1134 /* It is actually possible to have t->data NULL */
1135
1136 res = interpret(t->data);
1137 if (res.type & T_RETURN)
1138 return res;
1139 }
1140 break;
1141 case P('i','M'): /* IP.MASK(val) */
1142 TWOARGS;
1143 if (v2.type != T_INT)
1144 runtime( "Integer expected");
1145 if (v1.type != T_IP)
1146 runtime( "You can mask only IP addresses" );
1147 {
1148 ip_addr mask = ipa_mkmask(v2.val.i);
1149 res.type = T_IP;
1150 res.val.px.ip = ipa_and(mask, v1.val.px.ip);
1151 }
1152 break;
1153
1154 case 'E': /* Create empty attribute */
1155 res.type = what->aux;
1156 res.val.ad = adata_empty(f_pool, 0);
1157 break;
1158 case P('A','p'): /* Path prepend */
1159 TWOARGS;
1160 if (v1.type != T_PATH)
1161 runtime("Can't prepend to non-path");
1162 if (v2.type != T_INT)
1163 runtime("Can't prepend non-integer");
1164
1165 res.type = T_PATH;
1166 res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i);
1167 break;
1168
1169 case P('C','a'): /* (Extended) Community list add or delete */
1170 TWOARGS;
1171 if (v1.type == T_PATH)
1172 {
1173 struct f_tree *set = NULL;
1174 u32 key = 0;
1175 int pos;
1176
1177 if (v2.type == T_INT)
1178 key = v2.val.i;
1179 else if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT))
1180 set = v2.val.t;
1181 else
1182 runtime("Can't delete non-integer (set)");
1183
1184 switch (what->aux)
1185 {
1186 case 'a': runtime("Can't add to path");
1187 case 'd': pos = 0; break;
1188 case 'f': pos = 1; break;
1189 default: bug("unknown Ca operation");
1190 }
1191
1192 if (pos && !set)
1193 runtime("Can't filter integer");
1194
1195 res.type = T_PATH;
1196 res.val.ad = as_path_filter(f_pool, v1.val.ad, set, key, pos);
1197 }
1198 else if (v1.type == T_CLIST)
1199 {
1200 /* Community (or cluster) list */
1201 struct f_val dummy;
1202 int arg_set = 0;
1203 i = 0;
1204
1205 if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
1206 i = v2.val.i;
1207 #ifndef IPV6
1208 /* IP->Quad implicit conversion */
1209 else if (v2.type == T_IP)
1210 i = ipa_to_u32(v2.val.px.ip);
1211 #endif
1212 else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy))
1213 arg_set = 1;
1214 else if (v2.type == T_CLIST)
1215 arg_set = 2;
1216 else
1217 runtime("Can't add/delete non-pair");
1218
1219 res.type = T_CLIST;
1220 switch (what->aux)
1221 {
1222 case 'a':
1223 if (arg_set == 1)
1224 runtime("Can't add set");
1225 else if (!arg_set)
1226 res.val.ad = int_set_add(f_pool, v1.val.ad, i);
1227 else
1228 res.val.ad = int_set_union(f_pool, v1.val.ad, v2.val.ad);
1229 break;
1230
1231 case 'd':
1232 if (!arg_set)
1233 res.val.ad = int_set_del(f_pool, v1.val.ad, i);
1234 else
1235 res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 0);
1236 break;
1237
1238 case 'f':
1239 if (!arg_set)
1240 runtime("Can't filter pair");
1241 res.val.ad = clist_filter(f_pool, v1.val.ad, v2, 1);
1242 break;
1243
1244 default:
1245 bug("unknown Ca operation");
1246 }
1247 }
1248 else if (v1.type == T_ECLIST)
1249 {
1250 /* Extended community list */
1251 int arg_set = 0;
1252
1253 /* v2.val is either EC or EC-set */
1254 if ((v2.type == T_SET) && eclist_set_type(v2.val.t))
1255 arg_set = 1;
1256 else if (v2.type == T_ECLIST)
1257 arg_set = 2;
1258 else if (v2.type != T_EC)
1259 runtime("Can't add/delete non-pair");
1260
1261 res.type = T_ECLIST;
1262 switch (what->aux)
1263 {
1264 case 'a':
1265 if (arg_set == 1)
1266 runtime("Can't add set");
1267 else if (!arg_set)
1268 res.val.ad = ec_set_add(f_pool, v1.val.ad, v2.val.ec);
1269 else
1270 res.val.ad = ec_set_union(f_pool, v1.val.ad, v2.val.ad);
1271 break;
1272
1273 case 'd':
1274 if (!arg_set)
1275 res.val.ad = ec_set_del(f_pool, v1.val.ad, v2.val.ec);
1276 else
1277 res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 0);
1278 break;
1279
1280 case 'f':
1281 if (!arg_set)
1282 runtime("Can't filter ec");
1283 res.val.ad = eclist_filter(f_pool, v1.val.ad, v2, 1);
1284 break;
1285
1286 default:
1287 bug("unknown Ca operation");
1288 }
1289 }
1290 else
1291 runtime("Can't add/delete to non-(e)clist");
1292
1293 break;
1294
1295 case P('R','C'): /* ROA Check */
1296 if (what->arg1)
1297 {
1298 TWOARGS;
1299 if ((v1.type != T_PREFIX) || (v2.type != T_INT))
1300 runtime("Invalid argument to roa_check()");
1301
1302 as = v2.val.i;
1303 }
1304 else
1305 {
1306 ACCESS_RTE;
1307 v1.val.px.ip = (*f_rte)->net->n.prefix;
1308 v1.val.px.len = (*f_rte)->net->n.pxlen;
1309
1310 /* We ignore temporary attributes, probably not a problem here */
1311 /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
1312 eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
1313
1314 if (!e || e->type != EAF_TYPE_AS_PATH)
1315 runtime("Missing AS_PATH attribute");
1316
1317 as_path_get_last(e->u.ptr, &as);
1318 }
1319
1320 struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
1321 if (!rtc->table)
1322 runtime("Missing ROA table");
1323
1324 res.type = T_ENUM_ROA;
1325 res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
1326 break;
1327
1328 default:
1329 bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
1330 }
1331 if (what->next)
1332 return interpret(what->next);
1333 return res;
1334 }
1335
1336 #undef ARG
1337 #define ARG(x,y) \
1338 if (!i_same(f1->y, f2->y)) \
1339 return 0;
1340
1341 #define ONEARG ARG(v1, a1.p)
1342 #define TWOARGS ARG(v1, a1.p) \
1343 ARG(v2, a2.p)
1344
1345 #define A2_SAME if (f1->a2.i != f2->a2.i) return 0;
1346
1347 /*
1348 * i_same - function that does real comparing of instruction trees, you should call filter_same from outside
1349 */
1350 int
1351 i_same(struct f_inst *f1, struct f_inst *f2)
1352 {
1353 if ((!!f1) != (!!f2))
1354 return 0;
1355 if (!f1)
1356 return 1;
1357 if (f1->aux != f2->aux)
1358 return 0;
1359 if (f1->code != f2->code)
1360 return 0;
1361 if (f1 == f2) /* It looks strange, but it is possible with call rewriting trickery */
1362 return 1;
1363
1364 switch(f1->code) {
1365 case ',': /* fall through */
1366 case '+':
1367 case '-':
1368 case '*':
1369 case '/':
1370 case '|':
1371 case '&':
1372 case P('m','p'):
1373 case P('m','c'):
1374 case P('!','='):
1375 case P('=','='):
1376 case '<':
1377 case P('<','='): TWOARGS; break;
1378
1379 case '!': ONEARG; break;
1380 case '~': TWOARGS; break;
1381 case P('d','e'): ONEARG; break;
1382
1383 case 's':
1384 ARG(v2, a2.p);
1385 {
1386 struct symbol *s1, *s2;
1387 s1 = f1->a1.p;
1388 s2 = f2->a1.p;
1389 if (strcmp(s1->name, s2->name))
1390 return 0;
1391 if (s1->class != s2->class)
1392 return 0;
1393 }
1394 break;
1395
1396 case 'c':
1397 switch (f1->aux) {
1398
1399 case T_PREFIX_SET:
1400 if (!trie_same(f1->a2.p, f2->a2.p))
1401 return 0;
1402 break;
1403
1404 case T_SET:
1405 if (!same_tree(f1->a2.p, f2->a2.p))
1406 return 0;
1407 break;
1408
1409 case T_STRING:
1410 if (strcmp(f1->a2.p, f2->a2.p))
1411 return 0;
1412 break;
1413
1414 default:
1415 A2_SAME;
1416 }
1417 break;
1418
1419 case 'C':
1420 if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
1421 return 0;
1422 break;
1423
1424 case 'V':
1425 if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
1426 return 0;
1427 break;
1428 case 'p': case 'L': ONEARG; break;
1429 case '?': TWOARGS; break;
1430 case '0': case 'E': break;
1431 case P('p',','): ONEARG; A2_SAME; break;
1432 case 'P':
1433 case 'a': A2_SAME; break;
1434 case P('e','a'): A2_SAME; break;
1435 case P('P','S'):
1436 case P('a','S'):
1437 case P('e','S'): ONEARG; A2_SAME; break;
1438
1439 case 'r': ONEARG; break;
1440 case P('c','p'): ONEARG; break;
1441 case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */
1442 ONEARG;
1443 if (!i_same(f1->a2.p, f2->a2.p))
1444 return 0;
1445 f2->a2.p = f1->a2.p;
1446 break;
1447 case P('c','v'): break; /* internal instruction */
1448 case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break;
1449 case P('i','M'): TWOARGS; break;
1450 case P('A','p'): TWOARGS; break;
1451 case P('C','a'): TWOARGS; break;
1452 case P('a','f'):
1453 case P('a','l'): ONEARG; break;
1454 case P('R','C'):
1455 TWOARGS;
1456 /* Does not really make sense - ROA check resuls may change anyway */
1457 if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
1458 ((struct f_inst_roa_check *) f2)->rtc->name))
1459 return 0;
1460 break;
1461 default:
1462 bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
1463 }
1464 return i_same(f1->next, f2->next);
1465 }
1466
1467 /**
1468 * f_run - run a filter for a route
1469 * @filter: filter to run
1470 * @rte: route being filtered, may be modified
1471 * @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
1472 * @tmp_pool: all filter allocations go from this pool
1473 * @flags: flags
1474 *
1475 * If filter needs to modify the route, there are several
1476 * posibilities. @rte might be read-only (with REF_COW flag), in that
1477 * case rw copy is obtained by rte_cow() and @rte is replaced. If
1478 * @rte is originally rw, it may be directly modified (and it is never
1479 * copied).
1480 *
1481 * The returned rte may reuse the (possibly cached, cloned) rta, or
1482 * (if rta was modificied) contains a modified uncached rta, which
1483 * uses parts allocated from @tmp_pool and parts shared from original
1484 * rta. There is one exception - if @rte is rw but contains a cached
1485 * rta and that is modified, rta in returned rte is also cached.
1486 *
1487 * Ownership of cached rtas is consistent with rte, i.e.
1488 * if a new rte is returned, it has its own clone of cached rta
1489 * (and cached rta of read-only source rte is intact), if rte is
1490 * modified in place, old cached rta is possibly freed.
1491 */
1492 int
1493 f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
1494 {
1495 if (filter == FILTER_ACCEPT)
1496 return F_ACCEPT;
1497
1498 if (filter == FILTER_REJECT)
1499 return F_REJECT;
1500
1501 int rte_cow = ((*rte)->flags & REF_COW);
1502 DBG( "Running filter `%s'...", filter->name );
1503
1504 f_rte = rte;
1505 f_old_rta = NULL;
1506 f_tmp_attrs = tmp_attrs;
1507 f_pool = tmp_pool;
1508 f_flags = flags;
1509
1510 log_reset();
1511 struct f_val res = interpret(filter->root);
1512
1513 if (f_old_rta) {
1514 /*
1515 * Cached rta was modified and f_rte contains now an uncached one,
1516 * sharing some part with the cached one. The cached rta should
1517 * be freed (if rte was originally COW, f_old_rta is a clone
1518 * obtained during rte_cow()).
1519 *
1520 * This also implements the exception mentioned in f_run()
1521 * description. The reason for this is that rta reuses parts of
1522 * f_old_rta, and these may be freed during rta_free(f_old_rta).
1523 * This is not the problem if rte was COW, because original rte
1524 * also holds the same rta.
1525 */
1526 if (!rte_cow)
1527 (*f_rte)->attrs = rta_lookup((*f_rte)->attrs);
1528
1529 rta_free(f_old_rta);
1530 }
1531
1532
1533 if (res.type != T_RETURN) {
1534 log( L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name);
1535 return F_ERROR;
1536 }
1537 DBG( "done (%d)\n", res.val.i );
1538 return res.val.i;
1539 }
1540
1541 struct f_val
1542 f_eval(struct f_inst *expr, struct linpool *tmp_pool)
1543 {
1544 f_flags = 0;
1545 f_tmp_attrs = NULL;
1546 f_rte = NULL;
1547 f_pool = tmp_pool;
1548
1549 log_reset();
1550 return interpret(expr);
1551 }
1552
1553 int
1554 f_eval_int(struct f_inst *expr)
1555 {
1556 /* Called independently in parse-time to eval expressions */
1557 struct f_val res = f_eval(expr, cfg_mem);
1558
1559 if (res.type != T_INT)
1560 cf_error("Integer expression expected");
1561
1562 return res.val.i;
1563 }
1564
1565 u32
1566 f_eval_asn(struct f_inst *expr)
1567 {
1568 /* Called as a part of another interpret call, therefore no log_reset() */
1569 struct f_val res = interpret(expr);
1570 return (res.type == T_INT) ? res.val.i : 0;
1571 }
1572
1573 /**
1574 * filter_same - compare two filters
1575 * @new: first filter to be compared
1576 * @old: second filter to be compared, notice that this filter is
1577 * damaged while comparing.
1578 *
1579 * Returns 1 in case filters are same, otherwise 0. If there are
1580 * underlying bugs, it will rather say 0 on same filters than say
1581 * 1 on different.
1582 */
1583 int
1584 filter_same(struct filter *new, struct filter *old)
1585 {
1586 if (old == new) /* Handle FILTER_ACCEPT and FILTER_REJECT */
1587 return 1;
1588 if (old == FILTER_ACCEPT || old == FILTER_REJECT ||
1589 new == FILTER_ACCEPT || new == FILTER_REJECT)
1590 return 0;
1591 return i_same(new->root, old->root);
1592 }