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