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