From c0e958e022aac79f69e6aca2652fdb6a529e68e2 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Wed, 30 Jan 2019 14:03:47 +0100 Subject: Filter + Config: Fix bugs, tests and split symbols by type --- conf/cf-lex.l | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 9bbb3660..5e7c8418 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -285,7 +285,18 @@ else: { } cf_lval.s = cf_get_symbol(yytext); - return SYM; + switch (cf_lval.s->class) { + case SYM_VOID: return CF_SYM_VOID; + case SYM_PROTO: return CF_SYM_PROTO; + case SYM_TEMPLATE: return CF_SYM_TEMPLATE; + case SYM_FUNCTION: return CF_SYM_FUNCTION; + case SYM_FILTER: return CF_SYM_FILTER; + case SYM_TABLE: return CF_SYM_TABLE; + case SYM_ATTRIBUTE: return CF_SYM_ATTRIBUTE; + case SYM_VARIABLE_RANGE: return CF_SYM_VARIABLE; + case SYM_CONSTANT_RANGE: return CF_SYM_CONSTANT; + default: bug("Unknown symbol class %d", cf_lval.s->class); + } } (.|\n) { @@ -723,9 +734,6 @@ cf_pop_scope(void) char * cf_symbol_class_name(struct symbol *sym) { - if (cf_symbol_is_constant(sym)) - return "constant"; - switch (sym->class) { case SYM_VOID: @@ -740,6 +748,12 @@ cf_symbol_class_name(struct symbol *sym) return "filter"; case SYM_TABLE: return "routing table"; + case SYM_ATTRIBUTE: + return "custom attribute"; + case SYM_CONSTANT_RANGE: + return "constant"; + case SYM_VARIABLE_RANGE: + return "variable"; default: return "unknown type"; } -- cgit v1.2.3 From 8bdb05edb2b4e1d2989ed98d67992047ad69443c Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 7 Feb 2019 21:25:38 +0100 Subject: Filters: split the large filter.h file to smaller files. This should be revised, there are still ugly things in the filter API. --- conf/cf-lex.l | 1 + filter/config.Y | 3 + filter/f-inst.h | 276 +++++++++++++++++++++++++-------------- filter/f-util.c | 2 +- filter/f-util.h | 151 ++++++++++++++++++++++ filter/filter.c | 36 +++++- filter/filter.h | 358 +-------------------------------------------------- filter/filter_test.c | 2 + filter/new.m4 | 2 +- filter/tree.c | 1 + filter/tree_test.c | 1 + filter/trie.c | 1 + filter/trie_test.c | 1 + nest/a-path.c | 2 +- nest/cmds.c | 1 + nest/rt-table.c | 1 + sysdep/unix/main.c | 1 + 17 files changed, 381 insertions(+), 459 deletions(-) create mode 100644 filter/f-util.h (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 5e7c8418..6cc09425 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -45,6 +45,7 @@ #include "nest/route.h" #include "nest/protocol.h" #include "filter/filter.h" +#include "filter/f-inst.h" #include "conf/conf.h" #include "conf/cf-parse.tab.h" #include "lib/string.h" diff --git a/filter/config.Y b/filter/config.Y index 1306849f..31ceb3f5 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -10,6 +10,9 @@ CF_HDR +#include "filter/f-inst.h" +#include "filter/f-util.h" + CF_DEFINES static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } diff --git a/filter/f-inst.h b/filter/f-inst.h index 5c3d1d58..63124aa1 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -1,76 +1,99 @@ /* * BIRD Internet Routing Daemon -- Filter instructions * + * (c) 1999 Pavel Machek * (c) 2018--2019 Maria Matejka * * Can be freely distributed and used under the terms of the GNU GPL. */ -/* Filter instruction words */ -#define FI__TWOCHAR(a,b) ((a<<8) | b) +#ifndef _BIRD_F_INST_H_ +#define _BIRD_F_INST_H_ + +#include "filter/filter.h" +#include "filter/f-util.h" + +/* Filter l-value type */ +enum f_lval_type { + F_LVAL_VARIABLE, + F_LVAL_PREFERENCE, + F_LVAL_SA, + F_LVAL_EA, +}; + +/* Filter l-value */ +struct f_lval { + enum f_lval_type type; + union { + const struct symbol *sym; + struct f_dynamic_attr da; + struct f_static_attr sa; + }; +}; + +/* Filter instruction declarations */ #define FI__LIST \ - F(FI_NOP, 0, '0') \ - F(FI_ADD, 0, '+') \ - F(FI_SUBTRACT, 0, '-') \ - F(FI_MULTIPLY, 0, '*') \ - F(FI_DIVIDE, 0, '/') \ - F(FI_AND, 0, '&') \ - F(FI_OR, 0, '|') \ - F(FI_PAIR_CONSTRUCT, 'm', 'p') \ - F(FI_EC_CONSTRUCT, 'm', 'c') \ - F(FI_LC_CONSTRUCT, 'm', 'l') \ - F(FI_PATHMASK_CONSTRUCT, 'm', 'P') \ - F(FI_NEQ, '!', '=') \ - F(FI_EQ, '=', '=') \ - F(FI_LT, 0, '<') \ - F(FI_LTE, '<', '=') \ - F(FI_NOT, 0, '!') \ - F(FI_MATCH, 0, '~') \ - F(FI_NOT_MATCH, '!', '~') \ - F(FI_DEFINED, 'd', 'e') \ - F(FI_TYPE, 0, 'T') \ - F(FI_IS_V4, 'I', 'i') \ - F(FI_SET, 0, 's') \ - F(FI_CONSTANT, 0, 'c') \ - F(FI_VARIABLE, 0, 'V') \ - F(FI_CONSTANT_INDIRECT, 0, 'C') \ - F(FI_PRINT, 0, 'p') \ - F(FI_CONDITION, 0, '?') \ - F(FI_PRINT_AND_DIE, 'p', ',') \ - F(FI_RTA_GET, 0, 'a') \ - F(FI_RTA_SET, 'a', 'S') \ - F(FI_EA_GET, 'e', 'a') \ - F(FI_EA_SET, 'e', 'S') \ - F(FI_PREF_GET, 0, 'P') \ - F(FI_PREF_SET, 'P', 'S') \ - F(FI_LENGTH, 0, 'L') \ - F(FI_ROA_MAXLEN, 'R', 'M') \ - F(FI_ROA_ASN, 'R', 'A') \ - F(FI_SADR_SRC, 'n', 's') \ - F(FI_IP, 'c', 'p') \ - F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \ - F(FI_AS_PATH_FIRST, 'a', 'f') \ - F(FI_AS_PATH_LAST, 'a', 'l') \ - F(FI_AS_PATH_LAST_NAG, 'a', 'L') \ - F(FI_RETURN, 0, 'r') \ - F(FI_CALL, 'c', 'a') \ - F(FI_DROP_RESULT, 'd', 'r') \ - F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \ - F(FI_SWITCH, 'S', 'W') \ - F(FI_IP_MASK, 'i', 'M') \ - F(FI_PATH_PREPEND, 'A', 'p') \ - F(FI_CLIST_ADD, 'C', 'a') \ - F(FI_CLIST_DEL, 'C', 'd') \ - F(FI_CLIST_FILTER, 'C', 'f') \ - F(FI_ROA_CHECK_IMPLICIT, 'R', 'i') \ - F(FI_ROA_CHECK_EXPLICIT, 'R', 'e') \ - F(FI_FORMAT, 0, 'F') \ - F(FI_ASSERT, 'a', 's') + F(FI_NOP) \ + F(FI_ADD, ARG, ARG) \ + F(FI_SUBTRACT, ARG, ARG) \ + F(FI_MULTIPLY, ARG, ARG) \ + F(FI_DIVIDE, ARG, ARG) \ + F(FI_AND, ARG, LINE) \ + F(FI_OR, ARG, LINE) \ + F(FI_PAIR_CONSTRUCT, ARG, ARG) \ + F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \ + F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \ + F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \ + F(FI_NEQ, ARG, ARG) \ + F(FI_EQ, ARG, ARG) \ + F(FI_LT, ARG, ARG) \ + F(FI_LTE, ARG, ARG) \ + F(FI_NOT, ARG) \ + F(FI_MATCH, ARG, ARG) \ + F(FI_NOT_MATCH, ARG, ARG) \ + F(FI_DEFINED, ARG) \ + F(FI_TYPE, ARG) \ + F(FI_IS_V4, ARG) \ + F(FI_SET, ARG, SYMBOL) \ + F(FI_CONSTANT, VALI) \ + F(FI_VARIABLE, SYMBOL) \ + F(FI_CONSTANT_INDIRECT, VALP) \ + F(FI_PRINT, ARG) \ + F(FI_CONDITION, ARG, LINE, LINE) \ + F(FI_PRINT_AND_DIE, ARG, FRET) \ + F(FI_RTA_GET, SA) \ + F(FI_RTA_SET, ARG, SA) \ + F(FI_EA_GET, EA) \ + F(FI_EA_SET, ARG, EA) \ + F(FI_EA_UNSET, EA) \ + F(FI_PREF_GET) \ + F(FI_PREF_SET, ARG) \ + F(FI_LENGTH, ARG) \ + F(FI_ROA_MAXLEN, ARG) \ + F(FI_ROA_ASN, ARG) \ + F(FI_SADR_SRC, ARG) \ + F(FI_IP, ARG) \ + F(FI_ROUTE_DISTINGUISHER, ARG) \ + F(FI_AS_PATH_FIRST, ARG) \ + F(FI_AS_PATH_LAST, ARG) \ + F(FI_AS_PATH_LAST_NAG, ARG) \ + F(FI_RETURN, ARG) \ + F(FI_CALL, SYMBOL, LINE) \ + F(FI_DROP_RESULT, ARG) \ + F(FI_SWITCH, ARG, TREE) \ + F(FI_IP_MASK, ARG, ARG) \ + F(FI_PATH_PREPEND, ARG, ARG) \ + F(FI_CLIST_ADD, ARG, ARG) \ + F(FI_CLIST_DEL, ARG, ARG) \ + F(FI_CLIST_FILTER, ARG, ARG) \ + F(FI_ROA_CHECK_IMPLICIT, RTC) \ + F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \ + F(FI_FORMAT, ARG) \ + F(FI_ASSERT, ARG, STRING) /* The enum itself */ enum f_instruction_code { -#define F(c,a,b) \ - c, +#define F(c, ...) c, FI__LIST #undef F FI__MAX, @@ -79,46 +102,107 @@ FI__LIST /* Convert the instruction back to the enum name */ const char *f_instruction_name(enum f_instruction_code fi); +struct f_inst; +void f_inst_next(struct f_inst *first, const struct f_inst *append); +struct f_inst *f_clear_local_vars(struct f_inst *decls); + +#define FIA(x) , FIA_##x +#define FIA_ARG const struct f_inst * +#define FIA_LINE const struct f_inst * +#define FIA_COUNT uint +#define FIA_SYMBOL const struct symbol * +#define FIA_VALI struct f_val +#define FIA_VALP const struct f_val * +#define FIA_FRET enum filter_return +#define FIA_ECS enum ec_subtype +#define FIA_SA struct f_static_attr +#define FIA_EA struct f_dynamic_attr +#define FIA_RTC const struct rtable_config * +#define FIA_TREE const struct f_tree * +#define FIA_STRING const char * +#define F(c, ...) \ + struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__))); +FI__LIST +#undef F +#undef FIA_ARG +#undef FIA_LINE +#undef FIA_LINEP +#undef FIA_COUNT +#undef FIA_SYMBOL +#undef FIA_VALI +#undef FIA_VALP +#undef FIA_FRET +#undef FIA_ECS +#undef FIA_SA +#undef FIA_EA +#undef FIA_RTC +#undef FIA_STRING +#undef FIA + +#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) + +/* Flags for instructions */ +enum f_instruction_flags { + FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */ +}; +/* Filter structures for execution */ +struct f_line; -/* Instruction structure for config */ -struct f_inst { - const struct f_inst *next; /* Next instruction to be executed */ - union { /* Instruction content */ - struct { /* Instruction code for dispatching purposes */ - enum f_instruction_code fi_code; - }; - +/* The single instruction item */ +struct f_line_item { + enum f_instruction_code fi_code; /* What to do */ + enum f_instruction_flags flags; /* Flags, instruction-specific */ + uint lineno; /* Where */ + union { struct { - enum f_instruction_code fi_code_a; - const struct f_inst *p[3]; /* Three arguments at most */ + const struct f_val *vp; + const struct symbol *sym; }; + struct f_val val; + const struct f_line *lines[2]; + enum filter_return fret; + struct f_static_attr sa; + struct f_dynamic_attr da; + enum ec_subtype ecs; + const char *s; + const struct f_tree *tree; + const struct rtable_config *rtc; + uint count; + }; /* Additional instruction data */ +}; - struct { - - - - struct { - enum f_instruction_code - - - - - enum f_iknst - u16 aux; /* Extension to instruction code, T_*, EA_*, EAF_* */ - union { +/* Line of instructions to be unconditionally executed one after another */ +struct f_line { + uint len; /* Line length */ + struct f_line_item items[0]; /* The items themselves */ +}; - union f_inst_attr a[3]; /* The three arguments */ - struct f_val val; /* The value if FI_CONSTANT */ - struct { - union f_inst_attr sa_a[1]; - struct f_static_attr sa; /* Static attribute def for FI_RTA_* */ - }; - struct { - union f_inst_attr da_a[1]; - struct f_dynamic_attr da; /* Dynamic attribute def for FI_EA_* */ - }; - }; - int lineno; +/* Convert the f_inst infix tree to the f_line structures */ +struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint count); +static inline struct f_line *f_postfixify(const struct f_inst *root) +{ return f_postfixify_concat(&root, 1); } + +struct filter *f_new_where(const struct f_inst *); +static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ +{ return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ +static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly) +{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; } +struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument); +struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn); + +/* Hook for call bt_assert() function in configuration */ +extern void (*bt_assert_hook)(int result, const struct f_line_item *assert); + +/* Bird Tests */ +struct f_bt_test_suite { + node n; /* Node in config->tests */ + struct f_line *fn; /* Root of function */ + const char *fn_name; /* Name of test */ + const char *dsc; /* Description */ }; +/* Include the auto-generated structures */ +#include "filter/f-inst-struct.h" + +#endif diff --git a/filter/f-util.c b/filter/f-util.c index e94331b6..eb948fa0 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -10,7 +10,7 @@ #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-inst-struct.h" +#include "filter/f-inst.h" #include "lib/idm.h" #include "nest/protocol.h" #include "nest/route.h" diff --git a/filter/f-util.h b/filter/f-util.h new file mode 100644 index 00000000..a7d77bbd --- /dev/null +++ b/filter/f-util.h @@ -0,0 +1,151 @@ +/* + * BIRD Internet Routing Daemon -- Filter utils + * + * (c) 1999 Pavel Machek + * (c) 2018--2019 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_F_UTIL_H_ +#define _BIRD_F_UTIL_H_ + +/* IP prefix range structure */ +struct f_prefix { + net_addr net; /* The matching prefix must match this net */ + u8 lo, hi; /* And its length must fit between lo and hi */ +}; + +/* Type numbers must be in 0..0xff range */ +#define T_MASK 0xff + +/* Internal types */ +enum f_type { +/* Do not use type of zero, that way we'll see errors easier. */ + T_VOID = 1, + +/* User visible types, which fit in int */ + T_INT = 0x10, + T_BOOL = 0x11, + T_PAIR = 0x12, /* Notice that pair is stored as integer: first << 16 | second */ + T_QUAD = 0x13, + +/* Put enumerational types in 0x30..0x3f range */ + T_ENUM_LO = 0x30, + T_ENUM_HI = 0x3f, + + T_ENUM_RTS = 0x30, + T_ENUM_BGP_ORIGIN = 0x31, + T_ENUM_SCOPE = 0x32, + T_ENUM_RTC = 0x33, + T_ENUM_RTD = 0x34, + T_ENUM_ROA = 0x35, + T_ENUM_NETTYPE = 0x36, + T_ENUM_RA_PREFERENCE = 0x37, + +/* new enums go here */ + T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */ + +#define T_ENUM T_ENUM_LO ... T_ENUM_HI + +/* Bigger ones */ + T_IP = 0x20, + T_NET = 0x21, + T_STRING = 0x22, + T_PATH_MASK = 0x23, /* mask for BGP path */ + T_PATH = 0x24, /* BGP path */ + T_CLIST = 0x25, /* Community list */ + T_EC = 0x26, /* Extended community value, u64 */ + T_ECLIST = 0x27, /* Extended community list */ + T_LC = 0x28, /* Large community value, lcomm */ + T_LCLIST = 0x29, /* Large community list */ + T_RD = 0x2a, /* Route distinguisher for VPN addresses */ + T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */ + + T_SET = 0x80, + T_PREFIX_SET = 0x81, +} PACKED; + +/* Filter value; size of this affects filter memory consumption */ +struct f_val { + enum f_type type; /* T_* */ + union { + uint i; + u64 ec; + lcomm lc; + ip_addr ip; + const net_addr *net; + char *s; + const struct f_tree *t; + const struct f_trie *ti; + const struct adata *ad; + const struct f_path_mask *path_mask; + struct f_path_mask_item pmi; + } val; +}; + +#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); + +/* Dynamic attribute definition (eattrs) */ +struct f_dynamic_attr { + u8 type; /* EA type (EAF_*) */ + u8 bit; /* For bitfield accessors */ + enum f_type f_type; /* Filter type */ + uint ea_code; /* EA code */ +}; + +enum f_sa_code { + SA_FROM = 1, + SA_GW, + SA_NET, + SA_PROTO, + SA_SOURCE, + SA_SCOPE, + SA_DEST, + SA_IFNAME, + SA_IFINDEX, +} PACKED; + +/* Static attribute definition (members of struct rta) */ +struct f_static_attr { + enum f_type f_type; /* Filter type */ + enum f_sa_code sa_code; /* Static attribute id */ + int readonly:1; /* Don't allow writing */ +}; + +struct f_tree { + struct f_tree *left, *right; + struct f_val from, to; + void *data; +}; + +struct f_trie_node +{ + ip_addr addr, mask, accept; + uint plen; + struct f_trie_node *c[2]; +}; + +struct f_trie +{ + linpool *lp; + int zero; + uint node_size; + struct f_trie_node root[0]; /* Root trie node follows */ +}; + +struct f_tree *f_new_tree(void); +struct f_tree *build_tree(struct f_tree *); +const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val); +int same_tree(const struct f_tree *t0, const struct f_tree *t2); +void tree_format(const struct f_tree *t, buffer *buf); + +struct f_trie *f_new_trie(linpool *lp, uint node_size); +void *trie_add_prefix(struct f_trie *t, const net_addr *n, uint l, uint h); +int trie_match_net(const struct f_trie *t, const net_addr *n); +int trie_same(const struct f_trie *t1, const struct f_trie *t2); +void trie_format(const struct f_trie *t, buffer *buf); + +extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist; + +#endif diff --git a/filter/filter.c b/filter/filter.c index bb5e4235..ff702f2b 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -47,7 +47,8 @@ #include "nest/attrs.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-inst-struct.h" +#include "filter/f-inst.h" +#include "filter/f-util.h" #define CMP_ERROR 999 @@ -715,12 +716,39 @@ f_postfixify_concat(const struct f_inst * const inst[], uint count) static enum filter_return interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) { - struct f_val_stack vstk; + +#define F_VAL_STACK_MAX 4096 + /* Value stack for execution */ + struct f_val_stack { + uint cnt; /* Current stack size; 0 for empty */ + struct f_val val[F_VAL_STACK_MAX]; /* The stack itself */ + } vstk; + + /* The stack itself is intentionally kept as-is for performance reasons. + * Do NOT rewrite this to initialization by struct literal. It's slow. + */ vstk.cnt = 0; +#define F_EXEC_STACK_MAX 4096 + + /* Exception bits */ + enum f_exception { + FE_RETURN = 0x1, + }; - struct f_exec_stack estk; + /* Instruction stack for execution */ + struct f_exec_stack { + struct { + const struct f_line *line; /* The line that is being executed */ + uint pos; /* Instruction index in the line */ + uint ventry; /* Value stack depth on entry */ + enum f_exception emask; /* Exception mask */ + } item[F_EXEC_STACK_MAX]; + uint cnt; /* Current stack size; 0 for empty */ + } estk; + + /* The same as with the value stack. Not resetting the stack for performance reasons. */ estk.cnt = 1; - estk.item[0].line = line; + estk.item[0].line = line; estk.item[0].pos = 0; #define curline estk.item[estk.cnt-1] diff --git a/filter/filter.h b/filter/filter.h index 15a24fd4..9b3886fb 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -16,107 +16,6 @@ #include "nest/route.h" #include "nest/attrs.h" -/* IP prefix range structure */ -struct f_prefix { - net_addr net; /* The matching prefix must match this net */ - u8 lo, hi; /* And its length must fit between lo and hi */ -}; - -/* Type numbers must be in 0..0xff range */ -#define T_MASK 0xff - -/* Internal types */ -enum f_type { -/* Do not use type of zero, that way we'll see errors easier. */ - T_VOID = 1, - -/* User visible types, which fit in int */ - T_INT = 0x10, - T_BOOL = 0x11, - T_PAIR = 0x12, /* Notice that pair is stored as integer: first << 16 | second */ - T_QUAD = 0x13, - -/* Put enumerational types in 0x30..0x3f range */ - T_ENUM_LO = 0x30, - T_ENUM_HI = 0x3f, - - T_ENUM_RTS = 0x30, - T_ENUM_BGP_ORIGIN = 0x31, - T_ENUM_SCOPE = 0x32, - T_ENUM_RTC = 0x33, - T_ENUM_RTD = 0x34, - T_ENUM_ROA = 0x35, - T_ENUM_NETTYPE = 0x36, - T_ENUM_RA_PREFERENCE = 0x37, - -/* new enums go here */ - T_ENUM_EMPTY = 0x3f, /* Special hack for atomic_aggr */ - -#define T_ENUM T_ENUM_LO ... T_ENUM_HI - -/* Bigger ones */ - T_IP = 0x20, - T_NET = 0x21, - T_STRING = 0x22, - T_PATH_MASK = 0x23, /* mask for BGP path */ - T_PATH = 0x24, /* BGP path */ - T_CLIST = 0x25, /* Community list */ - T_EC = 0x26, /* Extended community value, u64 */ - T_ECLIST = 0x27, /* Extended community list */ - T_LC = 0x28, /* Large community value, lcomm */ - T_LCLIST = 0x29, /* Large community list */ - T_RD = 0x2a, /* Route distinguisher for VPN addresses */ - T_PATH_MASK_ITEM = 0x2b, /* Path mask item for path mask constructors */ - - T_SET = 0x80, - T_PREFIX_SET = 0x81, -} PACKED; - -/* Filter value; size of this affects filter memory consumption */ -struct f_val { - enum f_type type; /* T_* */ - union { - uint i; - u64 ec; - lcomm lc; - ip_addr ip; - const net_addr *net; - char *s; - const struct f_tree *t; - const struct f_trie *ti; - const struct adata *ad; - const struct f_path_mask *path_mask; - struct f_path_mask_item pmi; - } val; -}; - -/* Dynamic attribute definition (eattrs) */ -struct f_dynamic_attr { - u8 type; /* EA type (EAF_*) */ - u8 bit; /* For bitfield accessors */ - enum f_type f_type; /* Filter type */ - uint ea_code; /* EA code */ -}; - -enum f_sa_code { - SA_FROM = 1, - SA_GW, - SA_NET, - SA_PROTO, - SA_SOURCE, - SA_SCOPE, - SA_DEST, - SA_IFNAME, - SA_IFINDEX, -} PACKED; - -/* Static attribute definition (members of struct rta) */ -struct f_static_attr { - enum f_type f_type; /* Filter type */ - enum f_sa_code sa_code; /* Static attribute id */ - int readonly:1; /* Don't allow writing */ -}; - /* Possible return values of filter execution */ enum filter_return { F_NOP = 0, @@ -128,230 +27,15 @@ enum filter_return { F_QUITBIRD, }; -/* Filter l-value type */ -enum f_lval_type { - F_LVAL_VARIABLE, - F_LVAL_PREFERENCE, - F_LVAL_SA, - F_LVAL_EA, -}; - -/* Filter l-value */ -struct f_lval { - enum f_lval_type type; - union { - const struct symbol *sym; - struct f_dynamic_attr da; - struct f_static_attr sa; - }; -}; - -/* Filter instruction declarations */ -#define FI__LIST \ - F(FI_NOP) \ - F(FI_ADD, ARG, ARG) \ - F(FI_SUBTRACT, ARG, ARG) \ - F(FI_MULTIPLY, ARG, ARG) \ - F(FI_DIVIDE, ARG, ARG) \ - F(FI_AND, ARG, LINE) \ - F(FI_OR, ARG, LINE) \ - F(FI_PAIR_CONSTRUCT, ARG, ARG) \ - F(FI_EC_CONSTRUCT, ARG, ARG, ECS) \ - F(FI_LC_CONSTRUCT, ARG, ARG, ARG) \ - F(FI_PATHMASK_CONSTRUCT, ARG, COUNT) \ - F(FI_NEQ, ARG, ARG) \ - F(FI_EQ, ARG, ARG) \ - F(FI_LT, ARG, ARG) \ - F(FI_LTE, ARG, ARG) \ - F(FI_NOT, ARG) \ - F(FI_MATCH, ARG, ARG) \ - F(FI_NOT_MATCH, ARG, ARG) \ - F(FI_DEFINED, ARG) \ - F(FI_TYPE, ARG) \ - F(FI_IS_V4, ARG) \ - F(FI_SET, ARG, SYMBOL) \ - F(FI_CONSTANT, VALI) \ - F(FI_VARIABLE, SYMBOL) \ - F(FI_CONSTANT_INDIRECT, VALP) \ - F(FI_PRINT, ARG) \ - F(FI_CONDITION, ARG, LINE, LINE) \ - F(FI_PRINT_AND_DIE, ARG, FRET) \ - F(FI_RTA_GET, SA) \ - F(FI_RTA_SET, ARG, SA) \ - F(FI_EA_GET, EA) \ - F(FI_EA_SET, ARG, EA) \ - F(FI_EA_UNSET, EA) \ - F(FI_PREF_GET) \ - F(FI_PREF_SET, ARG) \ - F(FI_LENGTH, ARG) \ - F(FI_ROA_MAXLEN, ARG) \ - F(FI_ROA_ASN, ARG) \ - F(FI_SADR_SRC, ARG) \ - F(FI_IP, ARG) \ - F(FI_ROUTE_DISTINGUISHER, ARG) \ - F(FI_AS_PATH_FIRST, ARG) \ - F(FI_AS_PATH_LAST, ARG) \ - F(FI_AS_PATH_LAST_NAG, ARG) \ - F(FI_RETURN, ARG) \ - F(FI_CALL, SYMBOL, LINE) \ - F(FI_DROP_RESULT, ARG) \ - F(FI_SWITCH, ARG, TREE) \ - F(FI_IP_MASK, ARG, ARG) \ - F(FI_PATH_PREPEND, ARG, ARG) \ - F(FI_CLIST_ADD, ARG, ARG) \ - F(FI_CLIST_DEL, ARG, ARG) \ - F(FI_CLIST_FILTER, ARG, ARG) \ - F(FI_ROA_CHECK_IMPLICIT, RTC) \ - F(FI_ROA_CHECK_EXPLICIT, ARG, ARG, RTC) \ - F(FI_FORMAT, ARG) \ - F(FI_ASSERT, ARG, STRING) - -/* The enum itself */ -enum f_instruction_code { -#define F(c, ...) c, -FI__LIST -#undef F - FI__MAX, -} PACKED; - -/* Convert the instruction back to the enum name */ -const char *f_instruction_name(enum f_instruction_code fi); - -struct f_inst; -void f_inst_next(struct f_inst *first, const struct f_inst *append); -struct f_inst *f_clear_local_vars(struct f_inst *decls); - -#define FIA(x) , FIA_##x -#define FIA_ARG const struct f_inst * -#define FIA_LINE const struct f_inst * -#define FIA_COUNT uint -#define FIA_SYMBOL const struct symbol * -#define FIA_VALI struct f_val -#define FIA_VALP const struct f_val * -#define FIA_FRET enum filter_return -#define FIA_ECS enum ec_subtype -#define FIA_SA struct f_static_attr -#define FIA_EA struct f_dynamic_attr -#define FIA_RTC const struct rtable_config * -#define FIA_TREE const struct f_tree * -#define FIA_STRING const char * -#define F(c, ...) \ - struct f_inst *f_new_inst_##c(enum f_instruction_code MACRO_IFELSE(MACRO_ISLAST(__VA_ARGS__))()(MACRO_FOREACH(FIA, __VA_ARGS__))); -FI__LIST -#undef F -#undef FIA_ARG -#undef FIA_LINE -#undef FIA_LINEP -#undef FIA_COUNT -#undef FIA_SYMBOL -#undef FIA_VALI -#undef FIA_VALP -#undef FIA_FRET -#undef FIA_ECS -#undef FIA_SA -#undef FIA_EA -#undef FIA_RTC -#undef FIA_STRING -#undef FIA - -#define f_new_inst(...) MACRO_CONCAT_AFTER(f_new_inst_, MACRO_FIRST(__VA_ARGS__))(__VA_ARGS__) - -/* Flags for instructions */ -enum f_instruction_flags { - FIF_PRINTED = 1, /* FI_PRINT_AND_DIE: message put in buffer */ -}; - -/* Filter structures for execution */ -struct f_line; - -/* The single instruction item */ -struct f_line_item { - enum f_instruction_code fi_code; /* What to do */ - enum f_instruction_flags flags; /* Flags, instruction-specific */ - uint lineno; /* Where */ - union { - struct { - const struct f_val *vp; - const struct symbol *sym; - }; - struct f_val val; - const struct f_line *lines[2]; - enum filter_return fret; - struct f_static_attr sa; - struct f_dynamic_attr da; - enum ec_subtype ecs; - const char *s; - const struct f_tree *tree; - const struct rtable_config *rtc; - uint count; - }; /* Additional instruction data */ -}; - -/* Line of instructions to be unconditionally executed one after another */ -struct f_line { - uint len; /* Line length */ - struct f_line_item items[0]; /* The items themselves */ -}; +struct f_val; /* The filter encapsulating structure to be pointed-to from outside */ +struct f_line; struct filter { char *name; struct f_line *root; }; -/* Convert the f_inst infix tree to the f_line structures */ -struct f_line *f_postfixify_concat(const struct f_inst * const inst[], uint count); -static inline struct f_line *f_postfixify(const struct f_inst *root) -{ return f_postfixify_concat(&root, 1); } - -#define F_VAL_STACK_MAX 4096 - -/* Value stack for execution */ -struct f_val_stack { - uint cnt; /* Current stack size; 0 for empty */ - struct f_val val[F_VAL_STACK_MAX]; /* The stack itself */ -}; - -#define F_EXEC_STACK_MAX 4096 - -/* Exception bits */ -enum f_exception { - FE_RETURN = 0x1, -}; - -/* Instruction stack for execution */ -struct f_exec_stack { - struct { - const struct f_line *line; /* The line that is being executed */ - uint pos; /* Instruction index in the line */ - uint ventry; /* Value stack depth on entry */ - enum f_exception emask; /* Exception mask */ - } item[F_EXEC_STACK_MAX]; - uint cnt; /* Current stack size; 0 for empty */ -}; - -struct filter *f_new_where(const struct f_inst *); -static inline struct f_dynamic_attr f_new_dynamic_attr(u8 type, u8 bit, enum f_type f_type, uint code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ -{ return (struct f_dynamic_attr) { .type = type, .bit = bit, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ -static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly) -{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; } -struct f_tree *f_new_tree(void); -struct f_inst *f_generate_complex(enum f_instruction_code fi_code, struct f_dynamic_attr da, struct f_inst *argument); -struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn); - - -struct f_tree *build_tree(struct f_tree *); -const struct f_tree *find_tree(const struct f_tree *t, const struct f_val *val); -int same_tree(const struct f_tree *t1, const struct f_tree *t2); -void tree_format(const struct f_tree *t, buffer *buf); - -struct f_trie *f_new_trie(linpool *lp, uint node_size); -void *trie_add_prefix(struct f_trie *t, const net_addr *n, uint l, uint h); -int trie_match_net(const struct f_trie *t, const net_addr *n); -int trie_same(const struct f_trie *t1, const struct f_trie *t2); -void trie_format(const struct f_trie *t, buffer *buf); - -struct ea_list; struct rte; enum filter_return f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags); @@ -361,43 +45,16 @@ uint f_eval_int(const struct f_line *expr); char *filter_name(struct filter *filter); int filter_same(struct filter *new, struct filter *old); - int f_same(const struct f_line *f1, const struct f_line *f2); int val_compare(const struct f_val *v1, const struct f_val *v2); void val_format(const struct f_val *v, buffer *buf); -extern const struct f_val f_const_empty_path, f_const_empty_clist, f_const_empty_eclist, f_const_empty_lclist; - #define FILTER_ACCEPT NULL #define FILTER_REJECT ((void *) 1) #define FILTER_UNDEF ((void *) 2) /* Used in BGP */ - -struct f_tree { - struct f_tree *left, *right; - struct f_val from, to; - void *data; -}; - -struct f_trie_node -{ - ip_addr addr, mask, accept; - uint plen; - struct f_trie_node *c[2]; -}; - -struct f_trie -{ - linpool *lp; - int zero; - uint node_size; - struct f_trie_node root[0]; /* Root trie node follows */ -}; - -#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); - #define FF_SILENT 2 /* Silent filter execution */ /* Custom route attributes */ @@ -409,15 +66,4 @@ struct custom_attribute { struct custom_attribute *ca_lookup(pool *p, const char *name, int ea_type); -/* Bird Tests */ -struct f_bt_test_suite { - node n; /* Node in config->tests */ - struct f_line *fn; /* Root of function */ - const char *fn_name; /* Name of test */ - const char *dsc; /* Description */ -}; - -/* Hook for call bt_assert() function in configuration */ -extern void (*bt_assert_hook)(int result, const struct f_line_item *assert); - #endif diff --git a/filter/filter_test.c b/filter/filter_test.c index af6b590f..54ea3e9b 100644 --- a/filter/filter_test.c +++ b/filter/filter_test.c @@ -17,6 +17,8 @@ #include "test/bt-utils.h" #include "filter/filter.h" +#include "filter/f-util.h" +#include "filter/f-inst.h" #include "conf/conf.h" #define BT_CONFIG_FILE "filter/test.conf" diff --git a/filter/new.m4 b/filter/new.m4 index d499c94b..38295e5c 100644 --- a/filter/new.m4 +++ b/filter/new.m4 @@ -69,7 +69,7 @@ m4_divert(0) #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" -#include "filter/f-inst-struct.h" +#include "filter/f-inst.h" m4_undivert(1) diff --git a/filter/tree.c b/filter/tree.c index 80e1d395..879b0859 100644 --- a/filter/tree.c +++ b/filter/tree.c @@ -10,6 +10,7 @@ #include "nest/bird.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-util.h" /** * find_tree diff --git a/filter/tree_test.c b/filter/tree_test.c index f3e8ce49..9e0de50f 100644 --- a/filter/tree_test.c +++ b/filter/tree_test.c @@ -10,6 +10,7 @@ #include "test/bt-utils.h" #include "filter/filter.h" +#include "filter/f-util.h" #include "conf/conf.h" #define MAX_TREE_HEIGHT 13 diff --git a/filter/trie.c b/filter/trie.c index a279e38c..dccf9130 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -73,6 +73,7 @@ #include "lib/string.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-util.h" /* diff --git a/filter/trie_test.c b/filter/trie_test.c index 7529a5c5..b6959c4a 100644 --- a/filter/trie_test.c +++ b/filter/trie_test.c @@ -10,6 +10,7 @@ #include "test/bt-utils.h" #include "filter/filter.h" +#include "filter/f-util.h" #include "conf/conf.h" #define TESTS_NUM 10 diff --git a/nest/a-path.c b/nest/a-path.c index d3a1d636..ac13d0fa 100644 --- a/nest/a-path.c +++ b/nest/a-path.c @@ -13,7 +13,7 @@ #include "lib/resource.h" #include "lib/unaligned.h" #include "lib/string.h" -#include "filter/filter.h" +#include "filter/f-util.h" // static inline void put_as(byte *data, u32 as) { put_u32(data, as); } // static inline u32 get_as(byte *data) { return get_u32(data); } diff --git a/nest/cmds.c b/nest/cmds.c index 6daafcb3..40d397cc 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -15,6 +15,7 @@ #include "lib/string.h" #include "lib/resource.h" #include "filter/filter.h" +#include "filter/f-util.h" extern int shutting_down; extern int configuring; diff --git a/nest/rt-table.c b/nest/rt-table.c index 85afe838..d72a8695 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -39,6 +39,7 @@ #include "lib/string.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-util.h" #include "lib/hash.h" #include "lib/string.h" #include "lib/alloca.h" diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 921115b1..f9002d58 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -36,6 +36,7 @@ #include "nest/locks.h" #include "conf/conf.h" #include "filter/filter.h" +#include "filter/f-util.h" #include "unix.h" #include "krt.h" -- cgit v1.2.3 From 0b39b1cbb70c6f37a30a3130e1c308ddd0ba36de Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 15 Feb 2019 13:53:17 +0100 Subject: Conf: Symbol implementation converted from void pointers to union ... and consted some declarations. --- conf/cf-lex.l | 59 +++++++++++++++++++++++------------------------------- conf/conf.h | 49 +++++++++++++++++++++++++++++++++++++-------- conf/confbase.Y | 5 +++-- filter/config.Y | 53 ++++++++++++++++++++++++++---------------------- filter/decl.m4 | 4 ++-- filter/f-inst.c | 10 ++++----- filter/f-inst.h | 5 +++-- filter/f-util.c | 4 ++-- filter/filter.c | 5 ++--- filter/filter.h | 6 +++--- nest/config.Y | 24 +++++++++++----------- nest/proto.c | 6 +++--- nest/protocol.h | 6 +++--- nest/route.h | 4 ++-- nest/rt-table.c | 14 ++++++------- proto/mrt/mrt.h | 6 +++--- sysdep/unix/krt.c | 2 +- sysdep/unix/main.c | 8 +++----- 18 files changed, 149 insertions(+), 121 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 6cc09425..f1b402a0 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -539,11 +539,8 @@ cf_new_symbol(byte *c) if (l > SYM_MAX_LEN) cf_error("Symbol too long"); - s = cfg_alloc(sizeof(struct symbol) + l); - s->scope = conf_this_scope; - s->class = SYM_VOID; - s->def = NULL; - s->aux = 0; + s = cfg_allocz(sizeof(struct symbol) + l + 1); + *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, }; strcpy(s->name, c); if (!new_config->sym_hash.data) @@ -574,6 +571,7 @@ cf_find_symbol(struct config *cfg, byte *c) (s = HASH_FIND(cfg->sym_hash, SYM, c, 1))) return s; + /* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */ if (cfg->fallback && cfg->fallback->sym_hash.data && (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1))) @@ -597,6 +595,28 @@ cf_get_symbol(byte *c) return cf_find_symbol(new_config, c) ?: cf_new_symbol(c); } +/** + * cf_localize_symbol - get the local instance of given symbol + * @sym: the symbol to localize + * + * This functions finds the symbol that is local to current scope + * for purposes of cf_define_symbol(). + */ +struct symbol * +cf_localize_symbol(struct symbol *sym) +{ + /* If the symbol type is void, it has been recently allocated just in this scope. */ + if (!sym->class) + return sym; + + /* If the scope is the current, it is already defined in this scope. */ + if (sym->scope == conf_this_scope) + cf_error("Symbol already defined"); + + /* Not allocated here yet, doing it now. */ + return cf_new_symbol(sym->name); +} + struct symbol * cf_default_name(char *template, int *counter) { @@ -616,35 +636,6 @@ cf_default_name(char *template, int *counter) cf_error("Unable to generate default name"); } -/** - * cf_define_symbol - define meaning of a symbol - * @sym: symbol to be defined - * @type: symbol class to assign - * @def: class dependent data - * - * Defines new meaning of a symbol. If the symbol is an undefined - * one (%SYM_VOID), it's just re-defined to the new type. If it's defined - * in different scope, a new symbol in current scope is created and the - * meaning is assigned to it. If it's already defined in the current scope, - * an error is reported via cf_error(). - * - * Result: Pointer to the newly defined symbol. If we are in the top-level - * scope, it's the same @sym as passed to the function. - */ -struct symbol * -cf_define_symbol(struct symbol *sym, int type, void *def) -{ - if (sym->class) - { - if (sym->scope == conf_this_scope) - cf_error("Symbol already defined"); - sym = cf_new_symbol(sym->name); - } - sym->class = type; - sym->def = def; - return sym; -} - static void cf_lex_init_kh(void) { diff --git a/conf/conf.h b/conf/conf.h index 4e3addb3..21d4f1e2 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -105,11 +105,19 @@ extern int (*cf_read_hook)(byte *buf, uint max, int fd); struct symbol { struct symbol *next; struct sym_scope *scope; - int class; - int aux; - uint aux2; - void *def; - char name[1]; + int class; /* SYM_* */ + uint flags; /* SYM_FLAG_* */ + + union { + struct proto_config *proto; /* For SYM_PROTO and SYM_TEMPLATE */ + const struct f_line *function; /* For SYM_FUNCTION */ + const struct filter *filter; /* For SYM_FILTER */ + struct rtable_config *table; /* For SYM_TABLE */ + struct f_dynamic_attr *attribute; /* For SYM_ATTRIBUTE */ + struct f_val *val; /* For SYM_CONSTANT or SYM_VARIABLE */ + }; + + char name[0]; }; struct sym_scope { @@ -134,8 +142,11 @@ struct sym_scope { #define SYM_CONSTANT 0x200 /* 0x200-0x2ff are variable types */ #define SYM_CONSTANT_RANGE SYM_CONSTANT ... (SYM_CONSTANT | 0xff) -#define SYM_TYPE(s) (((struct f_val *) (s)->def)->type) -#define SYM_VAL(s) (((struct f_val *) (s)->def)->val) +#define SYM_TYPE(s) ((s)->val->type) +#define SYM_VAL(s) ((s)->val->val) + +/* Symbol flags */ +#define SYM_FLAG_SAME 0x1 /* For SYM_FUNCTION and SYM_FILTER */ struct include_file_stack { void *buffer; /* Internal lexer state */ @@ -160,7 +171,29 @@ struct symbol *cf_find_symbol(struct config *cfg, byte *c); struct symbol *cf_get_symbol(byte *c); struct symbol *cf_default_name(char *template, int *counter); -struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def); +struct symbol *cf_localize_symbol(struct symbol *sym); + +/** + * cf_define_symbol - define meaning of a symbol + * @sym: symbol to be defined + * @type: symbol class to assign + * @def: class dependent data + * + * Defines new meaning of a symbol. If the symbol is an undefined + * one (%SYM_VOID), it's just re-defined to the new type. If it's defined + * in different scope, a new symbol in current scope is created and the + * meaning is assigned to it. If it's already defined in the current scope, + * an error is reported via cf_error(). + * + * Result: Pointer to the newly defined symbol. If we are in the top-level + * scope, it's the same @sym as passed to the function. + */ +#define cf_define_symbol(sym_, type_, var_, def_) ({ \ + struct symbol *sym = cf_localize_symbol(sym_); \ + sym->class = type_; \ + sym->var_ = def_; \ + sym; }) + void cf_push_scope(struct symbol *); void cf_pop_scope(void); char *cf_symbol_class_name(struct symbol *sym); diff --git a/conf/confbase.Y b/conf/confbase.Y index 2195e8fc..62415b4c 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -56,7 +56,8 @@ CF_DECLS struct f_dynamic_attr fda; struct f_static_attr fsa; struct f_lval flv; - struct filter *f; + const struct f_line *fl; + const struct filter *f; struct f_tree *e; struct f_trie *trie; struct f_val v; @@ -130,7 +131,7 @@ definition: DEFINE CF_SYM_VOID '=' term ';' { struct f_val *val = cfg_alloc(sizeof(struct f_val)); if (f_eval(f_postfixify($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error"); - cf_define_symbol($2, SYM_CONSTANT | val->type, val); + cf_define_symbol($2, SYM_CONSTANT | val->type, val, val); } ; diff --git a/filter/config.Y b/filter/config.Y index 488b9ced..b3a04958 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -451,7 +451,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type term block cmd cmds constant constructor print_one print_list var_list var_listn function_call symbol_value bgp_path_expr bgp_path bgp_path_tail one_decl decls %type dynamic_attr %type static_attr -%type filter filter_body where_filter +%type filter where_filter +%type filter_body %type lvalue %type type %type ec_kind @@ -467,11 +468,12 @@ CF_GRAMMAR conf: filter_def ; filter_def: - FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); } + FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } filter_body { - $2->def = $4; - $4->name = $2->name; - DBG( "We have new filter defined (%s)\n", $2->name ); + struct filter *f = cfg_alloc(sizeof(struct filter)); + *f = (struct filter) { .name = $2->name, .root = $4 }; + $2->filter = f; + cf_pop_scope(); } ; @@ -483,14 +485,14 @@ filter_eval: conf: custom_attr ; custom_attr: ATTRIBUTE type CF_SYM_VOID ';' { - cf_define_symbol($3, SYM_ATTRIBUTE, ca_lookup(new_config->pool, $3->name, $2)->fda); + cf_define_symbol($3, SYM_ATTRIBUTE, attribute, ca_lookup(new_config->pool, $3->name, $2)->fda); }; conf: bt_test_suite ; bt_test_suite: BT_TEST_SUITE '(' CF_SYM_FUNCTION ',' text ')' { struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite)); - t->fn = $3->def; + t->fn = $3->function; t->fn_name = $3->name; t->dsc = $5; @@ -502,8 +504,8 @@ conf: bt_test_same ; bt_test_same: BT_TEST_SAME '(' CF_SYM_FUNCTION ',' CF_SYM_FUNCTION ',' NUM ')' { struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite)); - t->fn = $3->def; - t->cmp = $5->def; + t->fn = $3->function; + t->cmp = $5->function; t->result = $7; t->fn_name = $3->name; t->dsc = $5->name; @@ -553,7 +555,7 @@ one_decl: type CF_SYM_VOID { struct f_val * val = cfg_alloc(sizeof(struct f_val)); val->type = T_VOID; - $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val); + $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val, val); DBG( "New variable %s type %x\n", $2->name, $1 ); $$ = f_new_inst(FI_SET, NULL, $2); } @@ -578,22 +580,24 @@ declsn: one_decl { $$.inst = $1; $$.count = 1; } filter_body: function_body { - $$ = cfg_alloc(sizeof(struct filter)); - $$->name = NULL; if ($1[0]) { const struct f_inst *inst[2] = { $1[0], $1[1] }; - $$->root = f_postfixify_concat(inst, 2); + $$ = f_postfixify_concat(inst, 2); } else - $$->root = f_postfixify($1[1]); + $$ = f_postfixify($1[1]); } ; filter: CF_SYM_FILTER { - $$ = $1->def; + $$ = $1->filter; + } + | filter_body { + struct filter *f = cfg_alloc(sizeof(struct filter)); + *f = (struct filter) { .root = $1 }; + $$ = f; } - | filter_body ; where_filter: @@ -618,7 +622,7 @@ function_body: conf: function_def ; function_def: FUNCTION CF_SYM_VOID { DBG( "Beginning of function %s\n", $2->name ); - $2 = cf_define_symbol($2, SYM_FUNCTION, NULL); + $2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL); cf_push_scope($2); } function_params function_body { const struct f_inst *catlist[4]; @@ -639,9 +643,10 @@ function_def: if ($5[1]) catlist[count++] = $5[1]; - $2->def = f_postfixify_concat(catlist, count); - $2->aux2 = $4.count; - DBG("Hmm, we've got one function here - %s\n", $2->name); + struct f_line *fl = f_postfixify_concat(catlist, count); + fl->args = $4.count; + $2->function = fl; + cf_pop_scope(); } ; @@ -693,7 +698,7 @@ set_atom: } | CF_SYM_CONSTANT { if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name); - $$ = *(struct f_val *)($1->def); + $$ = *$1->val; } ; @@ -856,9 +861,9 @@ function_call: ; symbol_value: - CF_SYM_CONSTANT { $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->def); } + CF_SYM_CONSTANT { $$ = f_new_inst(FI_CONSTANT_INDIRECT, $1->val); } | CF_SYM_VARIABLE { $$ = f_new_inst(FI_VARIABLE, $1); } - | CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *((struct f_dynamic_attr *) $1->def)); } + | CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *$1->attribute); } ; static_attr: @@ -986,7 +991,7 @@ cmd: $$ = f_new_inst(FI_CONDITION, $2, $4, $6); } | CF_SYM_ATTRIBUTE '=' term ';' { - $$ = f_new_inst(FI_EA_SET, $3, *((struct f_dynamic_attr *) $1->def)); + $$ = f_new_inst(FI_EA_SET, $3, *$1->attribute); } | CF_SYM_VARIABLE '=' term ';' { $$ = f_new_inst(FI_SET, $3, $1); diff --git a/filter/decl.m4 b/filter/decl.m4 index 5ac62cbd..3043f4fc 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -188,9 +188,9 @@ const struct symbol *sym; FID_NEW_ARGS , const struct symbol *sym FID_NEW_BODY -what->valp = (what->sym = sym)->def; +what->valp = (what->sym = sym)->val; FID_POSTFIXIFY_BODY -dest->items[pos].vp = (dest->items[pos].sym = what->sym)->def; +dest->items[pos].vp = (dest->items[pos].sym = what->sym)->val; FID_SAME_BODY if (strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)) return 0; FID_DUMP_BODY diff --git a/filter/f-inst.c b/filter/f-inst.c index 4ab46529..6f563873 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -233,7 +233,7 @@ /* IP->Quad implicit conversion */ if ((sym->class == (SYM_VARIABLE | T_QUAD)) && val_is_ip4(&v1)) { - *((struct f_val *) sym->def) = (struct f_val) { + *(sym->val) = (struct f_val) { .type = T_QUAD, .val.i = ipa_to_u32(v1.val.ip), }; @@ -241,7 +241,7 @@ } runtime( "Assigning to variable of incompatible type" ); } - *((struct f_val *) sym->def) = v1; + *(sym->val) = v1; } /* some constants have value in a[1], some in *a[0].p, strange. */ @@ -709,7 +709,7 @@ /* Postfixify extracts the function body from the symbol */ FID_POSTFIXIFY_BODY - dest->items[pos].lines[0] = what->sym->def; + dest->items[pos].lines[0] = what->sym->function; FID_END /* First push the body on stack */ @@ -727,8 +727,8 @@ for (const struct f_inst *inst = f1; inst; inst = inst->next) count++; - if (count != sym->aux2) - cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->aux2, count); + if (count != sym->function->args) + cf_error("Function %s takes %u arguments, got %u.", sym->name, sym->function->args, count); FID_END /* FIXME: Optimization of function comparison. */ diff --git a/filter/f-inst.h b/filter/f-inst.h index e1d0b675..201be5f8 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -59,6 +59,7 @@ struct f_line_item { /* Line of instructions to be unconditionally executed one after another */ struct f_line { uint len; /* Line length */ + u16 args; /* Function: Args required */ struct f_line_item items[0]; /* The items themselves */ }; @@ -81,8 +82,8 @@ extern void (*bt_assert_hook)(int result, const struct f_line_item *assert); /* Bird Tests */ struct f_bt_test_suite { node n; /* Node in config->tests */ - struct f_line *fn; /* Root of function */ - struct f_line *cmp; /* Compare to this function */ + const struct f_line *fn; /* Root of function */ + const struct f_line *cmp; /* Compare to this function */ const char *fn_name; /* Name of test */ const char *dsc; /* Description */ int result; /* Desired result */ diff --git a/filter/f-util.c b/filter/f-util.c index 82aaa385..85f5d1c4 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -17,8 +17,8 @@ #define P(a,b) ((a<<8) | b) -char * -filter_name(struct filter *filter) +const char * +filter_name(const struct filter *filter) { if (!filter) return "ACCEPT"; diff --git a/filter/filter.c b/filter/filter.c index 29e78204..4249d4ee 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -359,15 +359,14 @@ f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf) /** * filter_same - compare two filters * @new: first filter to be compared - * @old: second filter to be compared, notice that this filter is - * damaged while comparing. + * @old: second filter to be compared * * Returns 1 in case filters are same, otherwise 0. If there are * underlying bugs, it will rather say 0 on same filters than say * 1 on different. */ int -filter_same(struct filter *new, struct filter *old) +filter_same(const struct filter *new, const struct filter *old) { if (old == new) /* Handle FILTER_ACCEPT and FILTER_REJECT */ return 1; diff --git a/filter/filter.h b/filter/filter.h index d03c6438..26faeaa3 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -48,7 +48,7 @@ struct f_val; struct f_line; struct filter { char *name; - struct f_line *root; + const struct f_line *root; }; struct rte; @@ -58,8 +58,8 @@ enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struc uint f_eval_int(const struct f_line *expr); enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf); -char *filter_name(struct filter *filter); -int filter_same(struct filter *new, struct filter *old); +const char *filter_name(const struct filter *filter); +int filter_same(const struct filter *new, const struct filter *old); int f_same(const struct f_line *f1, const struct f_line *f2); #define FILTER_ACCEPT NULL diff --git a/nest/config.Y b/nest/config.Y index fb75c593..c2622ed2 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -179,28 +179,28 @@ proto_name: /* EMPTY */ { struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); s->class = this_proto->class; - s->def = this_proto; + s->proto = this_proto; this_proto->name = s->name; } | CF_SYM_VOID { - cf_define_symbol($1, this_proto->class, this_proto); + cf_define_symbol($1, this_proto->class, proto, this_proto); this_proto->name = $1->name; } | FROM sym_proto_or_template { struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); s->class = this_proto->class; - s->def = this_proto; + s->proto = this_proto; this_proto->name = s->name; if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected"); - proto_copy_config(this_proto, $2->def); + proto_copy_config(this_proto, $2->proto); } | CF_SYM_VOID FROM sym_proto_or_template { - cf_define_symbol($1, this_proto->class, this_proto); + cf_define_symbol($1, this_proto->class, proto, this_proto); this_proto->name = $1->name; if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected"); - proto_copy_config(this_proto, $3->def); + proto_copy_config(this_proto, $3->proto); } ; @@ -256,7 +256,7 @@ channel_end: proto_channel: channel_start channel_opt_list channel_end; -rtable: CF_SYM_TABLE { $$ = $1->def; } ; +rtable: CF_SYM_TABLE { $$ = $1->table; } ; imexport: FILTER filter { $$ = $2; } @@ -544,7 +544,7 @@ r_args: } | r_args TABLE CF_SYM_TABLE { $$ = $1; - rt_show_add_table($$, ((struct rtable_config *)$3->def)->table); + rt_show_add_table($$, $3->table->table); $$->tables_defined_by = RSD_TDB_DIRECT; } | r_args TABLE ALL { @@ -556,7 +556,7 @@ r_args: } | r_args IMPORT TABLE CF_SYM_PROTO '.' r_args_channel { $$ = $1; - struct proto_config *cf = (void *) $4->def; + struct proto_config *cf = $4->proto; if (!cf->proto) cf_error("%s is not a protocol", $4->name); struct channel *c = proto_find_channel_by_name(cf->proto, $6); if (!c) cf_error("Channel %s.%s not found", $4->name, $6); @@ -587,7 +587,7 @@ r_args: $$->filtered = 1; } | r_args export_mode CF_SYM_PROTO { - struct proto_config *c = (struct proto_config *) $3->def; + struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); if (!c->proto) cf_error("%s is not a protocol", $3->name); @@ -596,7 +596,7 @@ r_args: $$->tables_defined_by = RSD_TDB_INDIRECT; } | r_args export_mode CF_SYM_PROTO '.' r_args_channel { - struct proto_config *c = (struct proto_config *) $3->def; + struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); if (!c->proto) cf_error("%s is not a protocol", $3->name); @@ -606,7 +606,7 @@ r_args: $$->tables_defined_by = RSD_TDB_INDIRECT; } | r_args PROTOCOL CF_SYM_PROTO { - struct proto_config *c = (struct proto_config *) $3->def; + struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->show_protocol) cf_error("Protocol specified twice"); if (!c->proto) cf_error("%s is not a protocol", $3->name); diff --git a/nest/proto.c b/nest/proto.c index d4a333d0..77bf082a 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -977,7 +977,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty { /* Found match, let's check if we can smoothly switch to new configuration */ /* No need to check description */ - nc = sym->def; + nc = sym->proto; nc->proto = p; /* We will try to reconfigure protocol p */ @@ -1905,7 +1905,7 @@ proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uintptr_t, return; } - cmd(((struct proto_config *)s->def)->proto, arg, 0); + cmd(s->proto->proto, arg, 0); cli_msg(0, ""); } @@ -1948,7 +1948,7 @@ proto_get_named(struct symbol *sym, struct protocol *pr) if (sym->class != SYM_PROTO) cf_error("%s: Not a protocol", sym->name); - p = ((struct proto_config *) sym->def)->proto; + p = sym->proto->proto; if (!p || p->proto != pr) cf_error("%s: Not a %s protocol", sym->name, pr->name); } diff --git a/nest/protocol.h b/nest/protocol.h index 6c04071b..82b46261 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -489,7 +489,7 @@ struct channel_config { struct proto_config *parent; /* Where channel is defined (proto or template) */ struct rtable_config *table; /* Table we're attached to */ - struct filter *in_filter, *out_filter; /* Attached filters */ + const struct filter *in_filter, *out_filter; /* Attached filters */ struct channel_limit rx_limit; /* Limit for receiving routes from protocol (relevant when in_keep_filtered is active) */ struct channel_limit in_limit; /* Limit for importing routes from protocol */ @@ -511,8 +511,8 @@ struct channel { struct proto *proto; struct rtable *table; - struct filter *in_filter; /* Input filter */ - struct filter *out_filter; /* Output filter */ + const struct filter *in_filter; /* Input filter */ + const struct filter *out_filter; /* Output filter */ struct channel_limit rx_limit; /* Receive limit (for in_keep_filtered) */ struct channel_limit in_limit; /* Input limit */ struct channel_limit out_limit; /* Output limit */ diff --git a/nest/route.h b/nest/route.h index c7ed80ff..7c9f3005 100644 --- a/nest/route.h +++ b/nest/route.h @@ -297,7 +297,7 @@ rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src); /* rte_update() moved to protocol.h to avoid dependency conflicts */ -int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); +int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter); rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent); void rt_refresh_begin(rtable *t, struct channel *c); void rt_refresh_end(rtable *t, struct channel *c); @@ -335,7 +335,7 @@ struct rt_show_data { struct rt_show_data_rtable *last_table; /* Last table in output */ struct fib_iterator fit; /* Iterator over networks in table */ int verbose, tables_defined_by; - struct filter *filter; + const struct filter *filter; struct proto *show_protocol; struct proto *export_protocol; struct channel *export_channel; diff --git a/nest/rt-table.c b/nest/rt-table.c index 6c8e662e..f05bd718 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -398,7 +398,7 @@ static rte * export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent) { struct proto *p = c->proto; - struct filter *filter = c->out_filter; + const struct filter *filter = c->out_filter; struct proto_stats *stats = &c->stats; rte *rt; int v; @@ -1362,7 +1362,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) { struct proto *p = c->proto; struct proto_stats *stats = &c->stats; - struct filter *filter = c->in_filter; + const struct filter *filter = c->in_filter; rte *dummy = NULL; net *nn; @@ -1503,7 +1503,7 @@ rte_modify(rte *old) /* Check rtable for best route to given net whether it would be exported do p */ int -rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) +rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter) { net *n = net_find(t, a); rte *rt = n ? n->routes : NULL; @@ -2106,13 +2106,13 @@ rt_new_table(struct symbol *s, uint addr_type) { /* Hack that allows to 'redefine' the master table */ if ((s->class == SYM_TABLE) && - (s->def == new_config->def_tables[addr_type]) && + (s->table == new_config->def_tables[addr_type]) && ((addr_type == NET_IP4) || (addr_type == NET_IP6))) - return s->def; + return s->table; struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config)); - cf_define_symbol(s, SYM_TABLE, c); + cf_define_symbol(s, SYM_TABLE, table, c); c->name = s->name; c->addr_type = addr_type; c->gc_max_ops = 1000; @@ -2171,7 +2171,7 @@ static struct rtable_config * rt_find_table_config(struct config *cf, char *name) { struct symbol *sym = cf_find_symbol(cf, name); - return (sym && (sym->class == SYM_TABLE)) ? sym->def : NULL; + return (sym && (sym->class == SYM_TABLE)) ? sym->table : NULL; } /** diff --git a/proto/mrt/mrt.h b/proto/mrt/mrt.h index b2cec09d..4dfb1b19 100644 --- a/proto/mrt/mrt.h +++ b/proto/mrt/mrt.h @@ -23,7 +23,7 @@ struct mrt_config { struct rtable_config *table_cf; const char *table_expr; - struct filter *filter; + const struct filter *filter; const char *filename; uint period; int always_add_path; @@ -41,7 +41,7 @@ struct mrt_proto { struct mrt_dump_data { const char *table_expr; struct rtable *table_ptr; - struct filter *filter; + const struct filter *filter; char *filename; }; @@ -61,7 +61,7 @@ struct mrt_table_dump_state { /* Configuration information */ const char *table_expr; /* Wildcard for table name (or NULL) */ struct rtable *table_ptr; /* Explicit table (or NULL) */ - struct filter *filter; /* Optional filter */ + const struct filter *filter; /* Optional filter */ const char *filename; /* Filename pattern */ int always_add_path; /* Always use *_ADDPATH message subtypes */ diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index ded5dfe4..24a4168d 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -562,7 +562,7 @@ static struct rte * krt_export_net(struct krt_proto *p, net *net, rte **rt_free) { struct channel *c = p->p.main_channel; - struct filter *filter = c->out_filter; + const struct filter *filter = c->out_filter; rte *rt; if (c->ra_mode == RA_MERGED) diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c index 0fdd5b34..b0d764fa 100644 --- a/sysdep/unix/main.c +++ b/sysdep/unix/main.c @@ -94,11 +94,9 @@ drop_gid(gid_t gid) static inline void add_num_const(char *name, int val) { - struct symbol *s = cf_get_symbol(name); - s->class = SYM_CONSTANT | T_INT; - s->def = cfg_allocz(sizeof(struct f_val)); - SYM_TYPE(s) = T_INT; - SYM_VAL(s).i = val; + struct f_val *v = cfg_alloc(sizeof(struct f_val)); + *v = (struct f_val) { .type = T_INT, .val.i = val }; + cf_define_symbol(cf_get_symbol(name), SYM_CONSTANT | T_INT, val, v); } /* the code of read_iproute_table() is based on -- cgit v1.2.3 From 99911873a196975f5221aad89ae5eac42e1330e0 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 25 Feb 2019 17:19:47 +0100 Subject: Conf: Lexer parses quoted strings in a more descriptive way --- conf/cf-lex.l | 137 ++++++++++++++++++++++++++++++++++++++-------------------- conf/conf.h | 4 +- 2 files changed, 92 insertions(+), 49 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index f1b402a0..45327cd9 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -65,7 +65,7 @@ struct keyword { #endif -static uint cf_hash(byte *c); +static uint cf_hash(const byte *c); #define KW_KEY(n) n->name #define KW_NEXT(n) n->next @@ -96,6 +96,15 @@ int (*cf_read_hook)(byte *buf, unsigned int max, int fd); struct include_file_stack *ifs; static struct include_file_stack *ifs_head; +#define QUOTED_BUFFER_SIZE 4096 +static BUFFER_(char) quoted_buffer; +static char quoted_buffer_data[QUOTED_BUFFER_SIZE]; +static inline void quoted_buffer_init(void) { + quoted_buffer.used = 0; + quoted_buffer.size = QUOTED_BUFFER_SIZE; + quoted_buffer.data = quoted_buffer_data; +} + #define MAX_INCLUDE_DEPTH 8 #define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd); @@ -106,6 +115,8 @@ static struct include_file_stack *ifs_head; static void cf_include(char *arg, int alen); static int check_eof(void); +static enum yytokentype cf_lex_symbol(const char *data); + %} %option noyywrap @@ -113,24 +124,26 @@ static int check_eof(void); %option nounput %option noreject -%x COMMENT CCOMM CLI +%x COMMENT CCOMM CLI QUOTED APOSTROPHED INCLUDE ALPHA [a-zA-Z_] DIGIT [0-9] XIGIT [0-9a-fA-F] ALNUM [a-zA-Z_0-9] WHITE [ \t] -include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*; %% -{include} { - char *start, *end; - +^{WHITE}*include{WHITE}*\" { if (!ifs->depth) cf_error("Include not allowed in CLI"); - start = strchr(yytext, '"'); - start++; + BEGIN(INCLUDE); +} + +[^"\n]+["]{WHITE}*; { + char *start, *end; + + start = yytext; end = strchr(start, '"'); *end = 0; @@ -139,8 +152,16 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*; cf_error("Include with empty argument"); cf_include(start, end-start); + + BEGIN(INITIAL); } +["] cf_error("Include with empty argument"); +. cf_error("Unterminated include"); +\n cf_error("Unterminated include"); +<> cf_error("Unterminated include"); + + {DIGIT}+:{DIGIT}+ { uint len1 UNUSED, len2; u64 l; @@ -267,37 +288,23 @@ else: { return ELSECOL; } -({ALPHA}{ALNUM}*|[']({ALNUM}|[-]|[\.]|[:])*[']) { - if(*yytext == '\'') { - yytext[yyleng-1] = 0; - yytext++; - } +['] { + BEGIN(APOSTROPHED); + quoted_buffer_init(); +} - struct keyword *k = HASH_FIND(kw_hash, KW, yytext); - if (k) - { - if (k->value > 0) - return k->value; - else - { - cf_lval.i = -k->value; - return ENUM; - } - } +{ALNUM}|[-]|[.:] BUFFER_PUSH(quoted_buffer) = yytext[0]; +\n cf_error("Unterminated symbol"); +<> cf_error("Unterminated symbol"); +['] { + BEGIN(INITIAL); + BUFFER_PUSH(quoted_buffer) = 0; + return cf_lex_symbol(quoted_buffer_data); +} +. cf_error("Invalid character in apostrophed symbol"); - cf_lval.s = cf_get_symbol(yytext); - switch (cf_lval.s->class) { - case SYM_VOID: return CF_SYM_VOID; - case SYM_PROTO: return CF_SYM_PROTO; - case SYM_TEMPLATE: return CF_SYM_TEMPLATE; - case SYM_FUNCTION: return CF_SYM_FUNCTION; - case SYM_FILTER: return CF_SYM_FILTER; - case SYM_TABLE: return CF_SYM_TABLE; - case SYM_ATTRIBUTE: return CF_SYM_ATTRIBUTE; - case SYM_VARIABLE_RANGE: return CF_SYM_VARIABLE; - case SYM_CONSTANT_RANGE: return CF_SYM_CONSTANT; - default: bug("Unknown symbol class %d", cf_lval.s->class); - } +({ALPHA}{ALNUM}*) { + return cf_lex_symbol(yytext); } (.|\n) { @@ -313,14 +320,21 @@ else: { return yytext[0]; } -["][^"\n]*["] { - yytext[yyleng-1] = 0; - cf_lval.t = cfg_strdup(yytext+1); - yytext[yyleng-1] = '"'; +["] { + BEGIN(QUOTED); + quoted_buffer_init(); +} + +\n cf_error("Unterminated string"); +<> cf_error("Unterminated string"); +["] { + BEGIN(INITIAL); + BUFFER_PUSH(quoted_buffer) = 0; + cf_lval.t = cfg_strdup(quoted_buffer_data); return TEXT; } -["][^"\n]*\n cf_error("Unterminated string"); +. BUFFER_PUSH(quoted_buffer) = yytext[0]; <> { if (check_eof()) return END; } @@ -361,7 +375,7 @@ else: { %% static uint -cf_hash(byte *c) +cf_hash(const byte *c) { uint h = 13 << 24; @@ -370,7 +384,6 @@ cf_hash(byte *c) return h; } - /* * IFS stack - it contains structures needed for recursive processing * of include in config files. On the top of the stack is a structure @@ -531,7 +544,7 @@ check_eof(void) } static struct symbol * -cf_new_symbol(byte *c) +cf_new_symbol(const byte *c) { struct symbol *s; @@ -563,7 +576,7 @@ cf_new_symbol(byte *c) * signify no match. */ struct symbol * -cf_find_symbol(struct config *cfg, byte *c) +cf_find_symbol(struct config *cfg, const byte *c) { struct symbol *s; @@ -590,7 +603,7 @@ cf_find_symbol(struct config *cfg, byte *c) * existing symbol is found. */ struct symbol * -cf_get_symbol(byte *c) +cf_get_symbol(const byte *c) { return cf_find_symbol(new_config, c) ?: cf_new_symbol(c); } @@ -636,6 +649,36 @@ cf_default_name(char *template, int *counter) cf_error("Unable to generate default name"); } +static enum yytokentype +cf_lex_symbol(const char *data) +{ + struct keyword *k = HASH_FIND(kw_hash, KW, data); + if (k) + { + if (k->value > 0) + return k->value; + else + { + cf_lval.i = -k->value; + return ENUM; + } + } + + cf_lval.s = cf_get_symbol(data); + switch (cf_lval.s->class) { + case SYM_VOID: return CF_SYM_VOID; + case SYM_PROTO: return CF_SYM_PROTO; + case SYM_TEMPLATE: return CF_SYM_TEMPLATE; + case SYM_FUNCTION: return CF_SYM_FUNCTION; + case SYM_FILTER: return CF_SYM_FILTER; + case SYM_TABLE: return CF_SYM_TABLE; + case SYM_ATTRIBUTE: return CF_SYM_ATTRIBUTE; + case SYM_VARIABLE_RANGE: return CF_SYM_VARIABLE; + case SYM_CONSTANT_RANGE: return CF_SYM_CONSTANT; + default: bug("Unknown symbol class %d", cf_lval.s->class); + } +} + static void cf_lex_init_kh(void) { diff --git a/conf/conf.h b/conf/conf.h index 21d4f1e2..acb3413b 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -167,9 +167,9 @@ int cf_lex(void); void cf_lex_init(int is_cli, struct config *c); void cf_lex_unwind(void); -struct symbol *cf_find_symbol(struct config *cfg, byte *c); +struct symbol *cf_find_symbol(struct config *cfg, const byte *c); -struct symbol *cf_get_symbol(byte *c); +struct symbol *cf_get_symbol(const byte *c); struct symbol *cf_default_name(char *template, int *counter); struct symbol *cf_localize_symbol(struct symbol *sym); -- cgit v1.2.3 From 2915e711f77d68dff756babd19af8da1677c4549 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Mon, 25 Feb 2019 23:28:36 +0100 Subject: Custom number parser to speed up config parsing The glibc's generic parser is slow due to its versatility. Specialized parsers for base-10 and base-16 are much faster and we don't use other bases. --- conf/cf-lex.l | 14 +++++++------- lib/Makefile | 2 +- lib/ip.c | 2 +- lib/string.h | 4 ++++ lib/strtoul.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 9 deletions(-) create mode 100644 lib/strtoul.c (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 45327cd9..593df9d6 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -168,7 +168,7 @@ WHITE [ \t] char *e; errno = 0; - l = strtoul(yytext, &e, 10); + l = bstrtoul(yytext, &e, 10); if (e && (*e != ':') || (errno == ERANGE) || (l >> 32)) cf_error("ASN out of range"); @@ -186,7 +186,7 @@ WHITE [ \t] } errno = 0; - l = strtoul(e+1, &e, 10); + l = bstrtoul(e+1, &e, 10); if (e && *e || (errno == ERANGE) || (l >> len2)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -213,13 +213,13 @@ WHITE [ \t] } errno = 0; - l = strtoul(yytext+2, &e, 10); + l = bstrtoul(yytext+2, &e, 10); if (e && (*e != ':') || (errno == ERANGE) || (l >> len1)) cf_error("ASN out of range"); cf_lval.i64 |= ((u64) l) << len2; errno = 0; - l = strtoul(e+1, &e, 10); + l = bstrtoul(e+1, &e, 10); if (e && *e || (errno == ERANGE) || (l >> len2)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -241,7 +241,7 @@ WHITE [ \t] cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16; errno = 0; - l = strtoul(e, &e, 10); + l = bstrtoul(e, &e, 10); if (e && *e || (errno == ERANGE) || (l >> 16)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -265,7 +265,7 @@ WHITE [ \t] char *e; unsigned long int l; errno = 0; - l = strtoul(yytext+2, &e, 16); + l = bstrtoul(yytext+2, &e, 16); if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l) cf_error("Number out of range"); cf_lval.i = l; @@ -276,7 +276,7 @@ WHITE [ \t] char *e; unsigned long int l; errno = 0; - l = strtoul(yytext, &e, 10); + l = bstrtoul(yytext, &e, 10); if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l) cf_error("Number out of range"); cf_lval.i = l; diff --git a/lib/Makefile b/lib/Makefile index 01f3114d..18816bb3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -src := bitops.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c timer.c xmalloc.c +src := bitops.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c obj := $(src-o-files) $(all-daemon) diff --git a/lib/ip.c b/lib/ip.c index 9497248c..0f5a5348 100644 --- a/lib/ip.c +++ b/lib/ip.c @@ -245,7 +245,7 @@ ip4_pton(const char *a, ip4_addr *o) char *d, *c = strchr(a, '.'); if (!c != !i) return 0; - l = strtoul(a, &d, 10); + l = bstrtoul(a, &d, 10); if (((d != c) && *d) || (l > 255)) return 0; ia = (ia << 8) | l; diff --git a/lib/string.h b/lib/string.h index 0d34f9c5..5f7c4666 100644 --- a/lib/string.h +++ b/lib/string.h @@ -24,6 +24,10 @@ int buffer_vprint(buffer *buf, const char *fmt, va_list args); int buffer_print(buffer *buf, const char *fmt, ...); void buffer_puts(buffer *buf, const char *str); +#define bstrtoul(str, end, base) bstrtoul##base(str, end) +u64 bstrtoul10(const char *str, char **end); +u64 bstrtoul16(const char *str, char **end); + int patmatch(const byte *pat, const byte *str); static inline char *xbasename(const char *str) diff --git a/lib/strtoul.c b/lib/strtoul.c new file mode 100644 index 00000000..44a1bb1d --- /dev/null +++ b/lib/strtoul.c @@ -0,0 +1,61 @@ +/* + * BIRD Library -- Parse numbers + * + * (c) 2019 Maria Matejka + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include "nest/bird.h" +#include "lib/string.h" + +#include + +#define ULI_MAX_DIV10 (UINT64_MAX / 10) +#define ULI_MAX_MOD10 (UINT64_MAX % 10) + +u64 +bstrtoul10(const char *str, char **end) +{ + u64 out = 0; + for (*end = (char *) str; (**end >= '0') && (**end <= '9'); (*end)++) { + u64 digit = **end - '0'; + if ((out > ULI_MAX_DIV10) || + (out == ULI_MAX_DIV10) && (digit > ULI_MAX_MOD10)) { + errno = ERANGE; + return UINT64_MAX; + } + + out *= 10; + out += (**end) - '0'; + } + return out; +} + +u64 +bstrtoul16(const char *str, char **end) +{ + u64 out = 0; + for (int i=0; i<=(64/4); i++) { + switch (str[i]) { + case '0' ... '9': + out *= 16; + out += str[i] - '0'; + break; + case 'a' ... 'f': + out *= 16; + out += str[i] + 10 - 'a'; + break; + case 'A' ... 'F': + out *= 16; + out += str[i] + 10 - 'A'; + break; + default: + *end = (char *) &(str[i]); + return out; + } + } + + errno = ERANGE; + return UINT64_MAX; +} -- cgit v1.2.3 From f249d0b84c840242a084966999a1d228c603b431 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 26 Feb 2019 16:44:24 +0100 Subject: Filters: comparison of functions and filters caching --- conf/cf-lex.l | 4 +++- conf/conf.c | 3 +++ conf/conf.h | 4 +++- filter/config.Y | 2 +- filter/f-inst.h | 4 +--- filter/f-util.c | 9 ++++----- filter/filter.c | 46 +++++++++++++++++++++++++++++++++++++++++-- filter/filter.h | 4 +++- filter/test-reconf-begin.conf | 23 ++++++++++++++++++++++ filter/test-reconf-end.conf | 23 ++++++++++++++++++++++ 10 files changed, 108 insertions(+), 14 deletions(-) create mode 100644 filter/test-reconf-begin.conf create mode 100644 filter/test-reconf-end.conf (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 593df9d6..4f69993e 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -561,6 +561,8 @@ cf_new_symbol(const byte *c) HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s); + add_tail(&(new_config->symbols), &(s->n)); + return s; } @@ -576,7 +578,7 @@ cf_new_symbol(const byte *c) * signify no match. */ struct symbol * -cf_find_symbol(struct config *cfg, const byte *c) +cf_find_symbol(const struct config *cfg, const byte *c) { struct symbol *s; diff --git a/conf/conf.c b/conf/conf.c index 439aa41d..b0980d7e 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -98,6 +98,7 @@ config_alloc(const char *name) memcpy(ndup, name, nlen); init_list(&c->tests); + init_list(&c->symbols); c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */ c->pool = p; c->mem = l; @@ -258,6 +259,8 @@ config_do_commit(struct config *c, int type) if (old_config) old_config->obstacle_count++; + DBG("filter_commit\n"); + filter_commit(c, old_config); DBG("sysdep_commit\n"); int force_restart = sysdep_commit(c, old_config); DBG("global_commit\n"); diff --git a/conf/conf.h b/conf/conf.h index acb3413b..f14c0e21 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -24,6 +24,7 @@ struct config { list tables; /* Configured routing tables (struct rtable_config) */ list logfiles; /* Configured log files (sysdep) */ list tests; /* Configured unit tests (f_bt_test_suite) */ + list symbols; /* Configured symbols in config order */ int mrtdump_file; /* Configured MRTDump file (sysdep, fd in unix) */ char *syslog_name; /* Name used for syslog (NULL -> no syslog) */ @@ -103,6 +104,7 @@ void cfg_copy_list(list *dest, list *src, unsigned node_size); extern int (*cf_read_hook)(byte *buf, uint max, int fd); struct symbol { + node n; /* In list of symbols in config */ struct symbol *next; struct sym_scope *scope; int class; /* SYM_* */ @@ -167,7 +169,7 @@ int cf_lex(void); void cf_lex_init(int is_cli, struct config *c); void cf_lex_unwind(void); -struct symbol *cf_find_symbol(struct config *cfg, const byte *c); +struct symbol *cf_find_symbol(const struct config *cfg, const byte *c); struct symbol *cf_get_symbol(const byte *c); struct symbol *cf_default_name(char *template, int *counter); diff --git a/filter/config.Y b/filter/config.Y index 5ec226f0..a7618987 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -470,7 +470,7 @@ filter_def: FILTER CF_SYM_VOID { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); } filter_body { struct filter *f = cfg_alloc(sizeof(struct filter)); - *f = (struct filter) { .name = $2->name, .root = $4 }; + *f = (struct filter) { .sym = $2, .root = $4 }; $2->filter = f; cf_pop_scope(); diff --git a/filter/f-inst.h b/filter/f-inst.h index 5b397a5d..4b42c57c 100644 --- a/filter/f-inst.h +++ b/filter/f-inst.h @@ -31,12 +31,10 @@ const char *f_instruction_name(enum f_instruction_code fi); struct f_inst *f_clear_local_vars(struct f_inst *decls); /* Filter structures for execution */ -struct f_line; - /* Line of instructions to be unconditionally executed one after another */ struct f_line { uint len; /* Line length */ - u16 args; /* Function: Args required */ + u8 args; /* Function: Args required */ struct f_line_item items[0]; /* The items themselves */ }; diff --git a/filter/f-util.c b/filter/f-util.c index 85f5d1c4..35944b2c 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -24,10 +24,10 @@ filter_name(const struct filter *filter) return "ACCEPT"; else if (filter == FILTER_REJECT) return "REJECT"; - else if (!filter->name) + else if (!filter->sym) return "(unnamed)"; else - return filter->name; + return filter->sym->name; } void f_inst_next(struct f_inst *first, const struct f_inst *append) @@ -54,7 +54,7 @@ struct filter *f_new_where(const struct f_inst *where) struct f_inst i = { .fi_code = FI_CONDITION, .lineno = ifs->lino, - .size = 3, + .size = 3 + where->size, .i_FI_CONDITION = { .f1 = where, .f2 = &acc, @@ -62,8 +62,7 @@ struct filter *f_new_where(const struct f_inst *where) }, }; - struct filter *f = cfg_alloc(sizeof(struct filter)); - f->name = NULL; + struct filter *f = cfg_allocz(sizeof(struct filter)); f->root = f_postfixify(&i); return f; } diff --git a/filter/filter.c b/filter/filter.c index ee5d5426..3be7343c 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -293,7 +293,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i if (fret < F_ACCEPT) { if (!(fs.flags & FF_SILENT)) - log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter->name); + log_rl(&rl_runtime_err, L_ERR "Filter %s did not return accept nor reject. Make up your mind", filter_name(filter)); return F_ERROR; } DBG( "done (%u)\n", res.val.i ); @@ -378,5 +378,47 @@ filter_same(const struct filter *new, const struct filter *old) if (old == FILTER_ACCEPT || old == FILTER_REJECT || new == FILTER_ACCEPT || new == FILTER_REJECT) return 0; - return f_same(new->root, old->root); + + if ((!old->sym) && (!new->sym)) + return f_same(new->root, old->root); + + if ((!old->sym) || (!new->sym)) + return 0; + + if (strcmp(old->sym->name, new->sym->name)) + return 0; + + return new->sym->flags & SYM_FLAG_SAME; +} + +/** + * filter_commit - do filter comparisons on all the named functions and filters + */ +void +filter_commit(const struct config *new, const struct config *old) +{ + if (!old) + return; + + struct symbol *sym, *osym; + WALK_LIST(sym, new->symbols) + switch (sym->class) { + case SYM_FUNCTION: + if ((osym = cf_find_symbol(old, sym->name)) && + (osym->class == SYM_FUNCTION) && + f_same(sym->function, osym->function)) + sym->flags |= SYM_FLAG_SAME; + else + sym->flags &= ~SYM_FLAG_SAME; + break; + + case SYM_FILTER: + if ((osym = cf_find_symbol(old, sym->name)) && + (osym->class == SYM_FILTER) && + f_same(sym->filter->root, osym->filter->root)) + sym->flags |= SYM_FLAG_SAME; + else + sym->flags &= ~SYM_FLAG_SAME; + break; + } } diff --git a/filter/filter.h b/filter/filter.h index 26faeaa3..d919cc74 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -47,7 +47,7 @@ struct f_val; /* The filter encapsulating structure to be pointed-to from outside */ struct f_line; struct filter { - char *name; + struct symbol *sym; const struct f_line *root; }; @@ -62,6 +62,8 @@ const char *filter_name(const struct filter *filter); int filter_same(const struct filter *new, const struct filter *old); int f_same(const struct f_line *f1, const struct f_line *f2); +void filter_commit(const struct config *new, const struct config *old); + #define FILTER_ACCEPT NULL #define FILTER_REJECT ((void *) 1) #define FILTER_UNDEF ((void *) 2) /* Used in BGP */ diff --git a/filter/test-reconf-begin.conf b/filter/test-reconf-begin.conf new file mode 100644 index 00000000..aeed007f --- /dev/null +++ b/filter/test-reconf-begin.conf @@ -0,0 +1,23 @@ +router id 1.1.1.1; +protocol device {} + +function a() { + return true; +} + +function b() { + return a(); +} + +function c() { + return b(); +} + +filter d { + if c() then accept; else reject; +} + +protocol static { + ipv4 { import filter d; }; + route 10.0.0.0/24 unreachable; +} diff --git a/filter/test-reconf-end.conf b/filter/test-reconf-end.conf new file mode 100644 index 00000000..19164825 --- /dev/null +++ b/filter/test-reconf-end.conf @@ -0,0 +1,23 @@ +router id 1.1.1.1; +protocol device {} + +function a() { + return false; +} + +function b() { + return a(); +} + +function c() { + return b(); +} + +filter d { + if c() then accept; else reject; +} + +protocol static { + ipv4 { import filter d; }; + route 10.0.0.0/24 unreachable; +} -- cgit v1.2.3 From 9eef9c648cee7179e069ea1f978d4e86cef580d3 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 17 May 2019 22:18:49 +0200 Subject: Lexer now returns known sym / unknown sym / keyword --- conf/cf-lex.l | 24 ++++++++++----------- conf/confbase.Y | 62 +++++++++++++++++++++++++++++++---------------------- filter/config.Y | 51 ++++++++++++++++++++++++++++++------------- nest/config.Y | 43 +++++++++++++++++++++---------------- proto/ospf/config.Y | 2 +- 5 files changed, 108 insertions(+), 74 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 4f69993e..83e4e77c 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -654,6 +654,14 @@ cf_default_name(char *template, int *counter) static enum yytokentype cf_lex_symbol(const char *data) { + /* Have we defined such a symbol? */ + struct symbol *sym = cf_get_symbol(data); + cf_lval.s = sym; + + if (sym->class != SYM_VOID) + return CF_SYM_KNOWN; + + /* Is it a keyword? */ struct keyword *k = HASH_FIND(kw_hash, KW, data); if (k) { @@ -666,19 +674,9 @@ cf_lex_symbol(const char *data) } } - cf_lval.s = cf_get_symbol(data); - switch (cf_lval.s->class) { - case SYM_VOID: return CF_SYM_VOID; - case SYM_PROTO: return CF_SYM_PROTO; - case SYM_TEMPLATE: return CF_SYM_TEMPLATE; - case SYM_FUNCTION: return CF_SYM_FUNCTION; - case SYM_FILTER: return CF_SYM_FILTER; - case SYM_TABLE: return CF_SYM_TABLE; - case SYM_ATTRIBUTE: return CF_SYM_ATTRIBUTE; - case SYM_VARIABLE_RANGE: return CF_SYM_VARIABLE; - case SYM_CONSTANT_RANGE: return CF_SYM_CONSTANT; - default: bug("Unknown symbol class %d", cf_lval.s->class); - } + /* OK, undefined symbol */ + cf_lval.s = sym; + return CF_SYM_UNDEFINED; } static void diff --git a/conf/confbase.Y b/conf/confbase.Y index dcc92365..e104e54f 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -33,6 +33,21 @@ check_u16(uint val) cf_error("Value %u out of range (0-65535)", val); } +#define cf_assert(cond, ...) do { if (!(cond)) cf_error(__VA_ARGS__); } while (0) +static inline void cf_assert_symbol(const struct symbol *sym, uint class) { + switch (class) { + case SYM_PROTO: cf_assert(sym->class == SYM_PROTO, "Protocol name required"); break; + case SYM_TEMPLATE: cf_assert(sym->class == SYM_TEMPLATE, "Protocol template name required"); break; + case SYM_FUNCTION: cf_assert(sym->class == SYM_FUNCTION, "Function name required"); break; + case SYM_FILTER: cf_assert(sym->class == SYM_FILTER, "Filter name required"); break; + case SYM_TABLE: cf_assert(sym->class == SYM_TABLE, "Table name required"); break; + case SYM_ATTRIBUTE: cf_assert(sym->class == SYM_ATTRIBUTE, "Custom attribute name required"); break; + case SYM_VARIABLE: cf_assert((sym->class & ~0xff) == SYM_VARIABLE, "Variable name required"); break; + case SYM_CONSTANT: cf_assert((sym->class & ~0xff) == SYM_CONSTANT, "Constant name required"); break; + default: bug("This shall not happen"); + } +} + CF_DECLS %union { @@ -82,7 +97,7 @@ CF_DECLS %token IP4 %token IP6 %token VPN_RD -%token CF_SYM_VOID CF_SYM_PROTO CF_SYM_TEMPLATE CF_SYM_FUNCTION CF_SYM_FILTER CF_SYM_TABLE CF_SYM_ATTRIBUTE CF_SYM_VARIABLE CF_SYM_CONSTANT +%token CF_SYM_KNOWN CF_SYM_UNDEFINED %token TEXT %type ipa_scope @@ -92,6 +107,7 @@ CF_DECLS %type net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa %type net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_ %type label_stack_start label_stack +%type CF_SYM_VOID %type text opttext %type symbol @@ -104,6 +120,8 @@ CF_DECLS %left '!' %nonassoc '.' +%start config + CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM) CF_GRAMMAR @@ -137,8 +155,8 @@ definition: expr: NUM | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } - | CF_SYM_CONSTANT { - if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected"); + | CF_SYM_KNOWN { + if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected"); $$ = SYM_VAL($1).i; } ; @@ -148,17 +166,9 @@ expr_us: | expr US { $$ = $1 US_; } ; -symbol: - CF_SYM_VOID - | CF_SYM_PROTO - | CF_SYM_TEMPLATE - | CF_SYM_FUNCTION - | CF_SYM_FILTER - | CF_SYM_TABLE - | CF_SYM_ATTRIBUTE - | CF_SYM_VARIABLE - | CF_SYM_CONSTANT - ; +CF_SYM_VOID: CF_SYM_UNDEFINED ; + +symbol: CF_SYM_VOID | CF_SYM_KNOWN ; /* Switches */ @@ -177,8 +187,8 @@ bool: ipa: IP4 { $$ = ipa_from_ip4($1); } | IP6 { $$ = ipa_from_ip6($1); } - | CF_SYM_CONSTANT { - if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); + | CF_SYM_KNOWN { + if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address constant expected"); $$ = SYM_VAL($1).ip; } ; @@ -292,27 +302,27 @@ net_: net_ip6: net_ip6_ - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6)) - cf_error("IPv6 network expected"); + cf_error("IPv6 network constant expected"); $$ = * SYM_VAL($1).net; } ; net_ip: net_ip_ - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net)) - cf_error("IP network expected"); + cf_error("IP network constant expected"); $$ = * SYM_VAL($1).net; } ; net_any: net_ - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if ($1->class != (SYM_CONSTANT | T_NET)) - cf_error("Network expected"); + cf_error("Network constant expected"); $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ } ; @@ -322,13 +332,13 @@ net_or_ipa: | net_ip6_ | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_IP)) net_fill_ip_host(&($$), SYM_VAL($1).ip); else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) $$ = * SYM_VAL($1).net; else - cf_error("IP address or network expected"); + cf_error("IP address or network constant expected"); } ; @@ -359,8 +369,8 @@ time: text: TEXT - | CF_SYM_CONSTANT { - if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected"); + | CF_SYM_KNOWN { + if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String constant expected"); $$ = SYM_VAL($1).s; } ; diff --git a/filter/config.Y b/filter/config.Y index a7618987..3eccc3ed 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -489,7 +489,8 @@ custom_attr: ATTRIBUTE type CF_SYM_VOID ';' { conf: bt_test_suite ; bt_test_suite: - BT_TEST_SUITE '(' CF_SYM_FUNCTION ',' text ')' { + BT_TEST_SUITE '(' CF_SYM_KNOWN ',' text ')' { + cf_assert_symbol($3, SYM_FUNCTION); struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite)); t->fn = $3->function; t->fn_name = $3->name; @@ -501,7 +502,9 @@ bt_test_suite: conf: bt_test_same ; bt_test_same: - BT_TEST_SAME '(' CF_SYM_FUNCTION ',' CF_SYM_FUNCTION ',' NUM ')' { + BT_TEST_SAME '(' CF_SYM_KNOWN ',' CF_SYM_KNOWN ',' NUM ')' { + cf_assert_symbol($3, SYM_FUNCTION); + cf_assert_symbol($5, SYM_FUNCTION); struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite)); t->fn = $3->function; t->cmp = $5->function; @@ -589,7 +592,8 @@ filter_body: ; filter: - CF_SYM_FILTER { + CF_SYM_KNOWN { + cf_assert_symbol($1, SYM_FILTER); $$ = $1->filter; } | filter_body { @@ -699,7 +703,8 @@ set_atom: if (f_eval(f_postfixify($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error"); if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type"); } - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { + cf_assert_symbol($1, SYM_CONSTANT); if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name); $$ = *$1->val; } @@ -858,15 +863,25 @@ constructor: function_call: - CF_SYM_FUNCTION '(' var_list ')' { + CF_SYM_KNOWN '(' var_list ')' { $$ = f_new_inst(FI_CALL, $1, $3); } ; -symbol_value: - CF_SYM_CONSTANT { $$ = f_new_inst(FI_VARIABLE, $1); } - | CF_SYM_VARIABLE { $$ = f_new_inst(FI_VARIABLE, $1); } - | CF_SYM_ATTRIBUTE { $$ = f_new_inst(FI_EA_GET, *$1->attribute); } +symbol_value: CF_SYM_KNOWN + { + switch ($1->class) { + case SYM_CONSTANT_RANGE: + case SYM_VARIABLE_RANGE: + $$ = f_new_inst(FI_VARIABLE, $1); + break; + case SYM_ATTRIBUTE: + $$ = f_new_inst(FI_EA_GET, *$1->attribute); + break; + default: + cf_error("Can't get value of symbol %s", $1->name); + } + } ; static_attr: @@ -993,11 +1008,17 @@ cmd: | IF term THEN block ELSE block { $$ = f_new_inst(FI_CONDITION, $2, $4, $6); } - | CF_SYM_ATTRIBUTE '=' term ';' { - $$ = f_new_inst(FI_EA_SET, $3, *$1->attribute); - } - | CF_SYM_VARIABLE '=' term ';' { - $$ = f_new_inst(FI_SET, $3, $1); + | CF_SYM_KNOWN '=' term ';' { + switch ($1->class) { + case SYM_VARIABLE_RANGE: + $$ = f_new_inst(FI_SET, $3, $1); + break; + case SYM_ATTRIBUTE: + $$ = f_new_inst(FI_EA_SET, $3, *$1->attribute); + break; + default: + cf_error("Can't assign to symbol %s", $1->name); + } } | RETURN term ';' { DBG( "Ook, we'll return the value\n" ); @@ -1038,7 +1059,7 @@ get_cf_position: }; lvalue: - CF_SYM_VARIABLE { $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; } + CF_SYM_KNOWN { cf_assert_symbol($1, SYM_VARIABLE); $$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 }; } | PREFERENCE { $$ = (struct f_lval) { .type = F_LVAL_PREFERENCE }; } | static_attr { $$ = (struct f_lval) { .type = F_LVAL_SA, .sa = $1 }; } | dynamic_attr { $$ = (struct f_lval) { .type = F_LVAL_EA, .da = $1 }; }; diff --git a/nest/config.Y b/nest/config.Y index c2622ed2..fe642489 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -88,7 +88,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) %type idval %type imexport %type rtable -%type optproto sym_proto_or_template +%type optproto %type r_args %type sym_args %type proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action net_type table_sorted tos password_algorithm @@ -114,7 +114,7 @@ idval: NUM { $$ = $1; } | '(' term ')' { $$ = f_eval_int(f_postfixify($2)); } | IP4 { $$ = ip4_to_u32($1); } - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) $$ = SYM_VAL($1).i; else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip)) @@ -173,8 +173,6 @@ proto_start: | TEMPLATE { $$ = SYM_TEMPLATE; } ; -sym_proto_or_template: CF_SYM_PROTO | CF_SYM_TEMPLATE ; - proto_name: /* EMPTY */ { struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); @@ -186,20 +184,22 @@ proto_name: cf_define_symbol($1, this_proto->class, proto, this_proto); this_proto->name = $1->name; } - | FROM sym_proto_or_template { + | FROM CF_SYM_KNOWN { + if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected"); + struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter); s->class = this_proto->class; s->proto = this_proto; this_proto->name = s->name; - if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected"); proto_copy_config(this_proto, $2->proto); } - | CF_SYM_VOID FROM sym_proto_or_template { + | CF_SYM_VOID FROM CF_SYM_KNOWN { + if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected"); + cf_define_symbol($1, this_proto->class, proto, this_proto); this_proto->name = $1->name; - if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected"); proto_copy_config(this_proto, $3->proto); } ; @@ -256,7 +256,7 @@ channel_end: proto_channel: channel_start channel_opt_list channel_end; -rtable: CF_SYM_TABLE { $$ = $1->table; } ; +rtable: CF_SYM_KNOWN { cf_assert_symbol($1, SYM_TABLE); $$ = $1->table; } ; imexport: FILTER filter { $$ = $2; } @@ -510,7 +510,7 @@ CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [ | \"\"], [[Show rou { proto_apply_cmd($4, proto_cmd_show, 0, 1); } ; optproto: - CF_SYM_PROTO + CF_SYM_KNOWN { cf_assert_symbol($1, SYM_PROTO); $$ = $1; } | /* empty */ { $$ = NULL; } ; @@ -542,7 +542,8 @@ r_args: $$->show_for = 1; $$->addr = $3; } - | r_args TABLE CF_SYM_TABLE { + | r_args TABLE CF_SYM_KNOWN { + cf_assert_symbol($3, SYM_TABLE); $$ = $1; rt_show_add_table($$, $3->table->table); $$->tables_defined_by = RSD_TDB_DIRECT; @@ -554,7 +555,8 @@ r_args: rt_show_add_table($$, t->table); $$->tables_defined_by = RSD_TDB_ALL; } - | r_args IMPORT TABLE CF_SYM_PROTO '.' r_args_channel { + | r_args IMPORT TABLE CF_SYM_KNOWN '.' r_args_channel { + cf_assert_symbol($4, SYM_PROTO); $$ = $1; struct proto_config *cf = $4->proto; if (!cf->proto) cf_error("%s is not a protocol", $4->name); @@ -586,7 +588,8 @@ r_args: $$ = $1; $$->filtered = 1; } - | r_args export_mode CF_SYM_PROTO { + | r_args export_mode CF_SYM_KNOWN { + cf_assert_symbol($3, SYM_PROTO); struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); @@ -595,7 +598,8 @@ r_args: $$->export_protocol = c->proto; $$->tables_defined_by = RSD_TDB_INDIRECT; } - | r_args export_mode CF_SYM_PROTO '.' r_args_channel { + | r_args export_mode CF_SYM_KNOWN '.' r_args_channel { + cf_assert_symbol($3, SYM_PROTO); struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->export_mode) cf_error("Export specified twice"); @@ -605,7 +609,8 @@ r_args: if (!$$->export_channel) cf_error("Export channel not found"); $$->tables_defined_by = RSD_TDB_INDIRECT; } - | r_args PROTOCOL CF_SYM_PROTO { + | r_args PROTOCOL CF_SYM_KNOWN { + cf_assert_symbol($3, SYM_PROTO); struct proto_config *c = (struct proto_config *) $3->proto; $$ = $1; if ($$->show_protocol) cf_error("Protocol specified twice"); @@ -643,7 +648,7 @@ r_args_for: $$ = cfg_alloc(sizeof(net_addr_ip6_sadr)); net_fill_ip6_sadr($$, $1, IP6_MAX_PREFIX_LENGTH, $3, IP6_MAX_PREFIX_LENGTH); } - | CF_SYM_CONSTANT { + | CF_SYM_KNOWN { if ($1->class == (SYM_CONSTANT | T_IP)) { $$ = cfg_alloc(ipa_is_ip4(SYM_VAL($1).ip) ? sizeof(net_addr_ip4) : sizeof(net_addr_ip6)); @@ -652,7 +657,7 @@ r_args_for: else if (($1->class == (SYM_CONSTANT | T_NET)) && net_type_match(SYM_VAL($1).net, NB_IP | NB_VPN)) $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ else - cf_error("IP address or network expected"); + cf_error("IP address or network constant expected"); } ; @@ -775,13 +780,13 @@ CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]]) { this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ; proto_patt: - CF_SYM_PROTO { $$.ptr = $1; $$.patt = 0; } + CF_SYM_KNOWN { cf_assert_symbol($1, SYM_PROTO); $$.ptr = $1; $$.patt = 0; } | ALL { $$.ptr = NULL; $$.patt = 1; } | TEXT { $$.ptr = $1; $$.patt = 1; } ; proto_patt2: - CF_SYM_PROTO { $$.ptr = $1; $$.patt = 0; } + CF_SYM_KNOWN { cf_assert_symbol($1, SYM_PROTO); $$.ptr = $1; $$.patt = 0; } | { $$.ptr = NULL; $$.patt = 1; } | TEXT { $$.ptr = $1; $$.patt = 1; } ; diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 38b09deb..66cf60c1 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -544,7 +544,7 @@ lsadb_args: | lsadb_args LSID idval { $$ = $1; $$->lsid = $3; } | lsadb_args SELF { $$ = $1; $$->router = SH_ROUTER_SELF; } | lsadb_args ROUTER idval { $$ = $1; $$->router = $3; } - | lsadb_args CF_SYM_PROTO { $$ = $1; $$->proto = (struct ospf_proto *) proto_get_named($2, &proto_ospf); } + | lsadb_args CF_SYM_KNOWN { cf_assert_symbol($2, SYM_PROTO); $$ = $1; $$->proto = (struct ospf_proto *) proto_get_named($2, &proto_ospf); } ; CF_CODE -- cgit v1.2.3 From 5c864e2cfaf5ff5e8e3db3ccd746162fbc7aac5b Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Thu, 13 Jun 2019 14:27:58 +0200 Subject: String: bstrtoul macro expanded to bstrtoul10 and 16 --- conf/cf-lex.l | 14 +++++++------- lib/ip.c | 2 +- lib/string.h | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 83e4e77c..09f3db8d 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -168,7 +168,7 @@ WHITE [ \t] char *e; errno = 0; - l = bstrtoul(yytext, &e, 10); + l = bstrtoul10(yytext, &e); if (e && (*e != ':') || (errno == ERANGE) || (l >> 32)) cf_error("ASN out of range"); @@ -186,7 +186,7 @@ WHITE [ \t] } errno = 0; - l = bstrtoul(e+1, &e, 10); + l = bstrtoul10(e+1, &e); if (e && *e || (errno == ERANGE) || (l >> len2)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -213,13 +213,13 @@ WHITE [ \t] } errno = 0; - l = bstrtoul(yytext+2, &e, 10); + l = bstrtoul10(yytext+2, &e); if (e && (*e != ':') || (errno == ERANGE) || (l >> len1)) cf_error("ASN out of range"); cf_lval.i64 |= ((u64) l) << len2; errno = 0; - l = bstrtoul(e+1, &e, 10); + l = bstrtoul10(e+1, &e); if (e && *e || (errno == ERANGE) || (l >> len2)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -241,7 +241,7 @@ WHITE [ \t] cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16; errno = 0; - l = bstrtoul(e, &e, 10); + l = bstrtoul10(e, &e); if (e && *e || (errno == ERANGE) || (l >> 16)) cf_error("Number out of range"); cf_lval.i64 |= l; @@ -265,7 +265,7 @@ WHITE [ \t] char *e; unsigned long int l; errno = 0; - l = bstrtoul(yytext+2, &e, 16); + l = bstrtoul16(yytext+2, &e); if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l) cf_error("Number out of range"); cf_lval.i = l; @@ -276,7 +276,7 @@ WHITE [ \t] char *e; unsigned long int l; errno = 0; - l = bstrtoul(yytext, &e, 10); + l = bstrtoul10(yytext, &e); if (e && *e || errno == ERANGE || (unsigned long int)(unsigned int) l != l) cf_error("Number out of range"); cf_lval.i = l; diff --git a/lib/ip.c b/lib/ip.c index 0f5a5348..2d195160 100644 --- a/lib/ip.c +++ b/lib/ip.c @@ -245,7 +245,7 @@ ip4_pton(const char *a, ip4_addr *o) char *d, *c = strchr(a, '.'); if (!c != !i) return 0; - l = bstrtoul(a, &d, 10); + l = bstrtoul10(a, &d); if (((d != c) && *d) || (l > 255)) return 0; ia = (ia << 8) | l; diff --git a/lib/string.h b/lib/string.h index 5f7c4666..6e549cb7 100644 --- a/lib/string.h +++ b/lib/string.h @@ -24,7 +24,6 @@ int buffer_vprint(buffer *buf, const char *fmt, va_list args); int buffer_print(buffer *buf, const char *fmt, ...); void buffer_puts(buffer *buf, const char *str); -#define bstrtoul(str, end, base) bstrtoul##base(str, end) u64 bstrtoul10(const char *str, char **end); u64 bstrtoul16(const char *str, char **end); -- cgit v1.2.3 From 63e7620462b80c9c6bbbd4f128b6816e0748d6c6 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 25 Jun 2019 16:18:06 +0200 Subject: Conf/Filters: Moved argument count to conf scope --- conf/cf-lex.l | 1 + conf/conf.h | 1 + filter/config.Y | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 09f3db8d..0aa9273f 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -742,6 +742,7 @@ cf_push_scope(struct symbol *sym) conf_this_scope = s; s->active = 1; s->name = sym; + s->slots = 0; } /** diff --git a/conf/conf.h b/conf/conf.h index d88d9a44..708a1034 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -126,6 +126,7 @@ struct symbol { struct sym_scope { struct sym_scope *next; /* Next on scope stack */ struct symbol *name; /* Name of this scope */ + uint slots; /* Variable slots */ int active; /* Currently entered */ }; diff --git a/filter/config.Y b/filter/config.Y index 3898748c..72866bb0 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -15,8 +15,6 @@ CF_HDR CF_DEFINES -static uint decls_count; - static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } @@ -455,7 +453,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %type filter where_filter %type filter_body function_body %type lvalue -%type type function_params +%type type function_params declsn decls %type ec_kind %type break_command %type cnum @@ -557,22 +555,24 @@ type: /* Declarations with ';' at the end */ decls: - /* EMPTY */ - | declsn ';' + /* EMPTY */ { $$ = 0; } + | declsn ';' { $$ = $1; } ; /* Declarations that have no ';' at the end. */ declsn: type CF_SYM_VOID { - cf_define_symbol($2, SYM_VARIABLE | $1, offset, decls_count++); + cf_define_symbol($2, SYM_VARIABLE | $1, offset, $2->scope->slots++); + $$ = $2->scope->slots; } | declsn ';' type CF_SYM_VOID { - if (decls_count >= 0xff) cf_error("Too many declarations, at most 255 allowed"); - cf_define_symbol($4, SYM_VARIABLE | $3, offset, decls_count++); + if ($4->scope->slots >= 0xff) cf_error("Too many declarations, at most 255 allowed"); + cf_define_symbol($4, SYM_VARIABLE | $3, offset, $4->scope->slots++); + $$ = $4->scope->slots; } ; -filter_body: { decls_count = 0; } function_body { $$ = $2; } ; +filter_body: function_body ; filter: CF_SYM_KNOWN { @@ -594,14 +594,14 @@ where_filter: ; function_params: - '(' declsn ')' { $$ = decls_count; } + '(' declsn ')' { $$ = $2; } | '(' ')' { $$ = 0; } ; function_body: decls '{' cmds '}' { $$ = f_linearize($3); - $$->vars = decls_count; + $$->vars = $1; } ; @@ -610,7 +610,6 @@ function_def: FUNCTION CF_SYM_VOID { DBG( "Beginning of function %s\n", $2->name ); $2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL); cf_push_scope($2); - decls_count = 0; } function_params function_body { $5->vars -= $4; $5->args = $4; -- cgit v1.2.3 From b40c0f028f37086991fefa9197708ba8c7b3d571 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 2 Jul 2019 10:45:53 +0200 Subject: Filter: Pre-evaluation of constant expressions --- conf/cf-lex.l | 1 + filter/Makefile | 3 +- filter/data.c | 9 +++++ filter/data.h | 3 +- filter/decl.m4 | 109 ++++++++++++++++++++++++++++++++++-------------------- filter/f-inst.c | 113 +++++++++++++++++++++++++++++++++++--------------------- filter/filter.c | 13 +++---- lib/resource.h | 10 +++-- 8 files changed, 165 insertions(+), 96 deletions(-) (limited to 'conf/cf-lex.l') diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 0aa9273f..38250d90 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -757,6 +757,7 @@ cf_pop_scope(void) { conf_this_scope->active = 0; conf_this_scope = conf_this_scope->next; + ASSERT(conf_this_scope); } diff --git a/filter/Makefile b/filter/Makefile index b2f8d96d..c2062534 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -3,7 +3,8 @@ obj := $(src-o-files) $(all-daemon) $(cf-local) -M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS)) +#M4FLAGS_FILTERS=$(filter-out -s,$(M4FLAGS)) +M4FLAGS_FILTERS=$(M4FLAGS) $(o)inst-gen.h: $(s)decl.m4 $(s)f-inst.c $(objdir)/.dir-stamp $(M4) $(M4FLAGS_FILTERS) -DTARGET=H -P $^ >$@ diff --git a/filter/data.c b/filter/data.c index 912e2b00..db55070f 100644 --- a/filter/data.c +++ b/filter/data.c @@ -514,6 +514,15 @@ val_format(const struct f_val *v, buffer *buf) } } +char * +val_format_str(struct linpool *lp, const struct f_val *v) { + buffer b; + LOG_BUFFER_INIT(b); + val_format(v, &b); + return lp_strdup(lp, b.start); +} + + static char val_dump_buffer[1024]; const char * val_dump(const struct f_val *v) { diff --git a/filter/data.h b/filter/data.h index 6973008f..083595f4 100644 --- a/filter/data.h +++ b/filter/data.h @@ -119,7 +119,7 @@ enum f_lval_type { struct f_lval { enum f_lval_type type; union { - const struct symbol *sym; + struct symbol *sym; struct f_dynamic_attr da; struct f_static_attr sa; }; @@ -169,6 +169,7 @@ void trie_format(const struct f_trie *t, buffer *buf); int val_same(const struct f_val *v1, const struct f_val *v2); int val_compare(const struct f_val *v1, const struct f_val *v2); void val_format(const struct f_val *v, buffer *buf); +char *val_format_str(struct linpool *lp, const struct f_val *v); const char *val_dump(const struct f_val *v); static inline int val_is_ip4(const struct f_val *v) diff --git a/filter/decl.m4 b/filter/decl.m4 index 786fee31..cc069485 100644 --- a/filter/decl.m4 +++ b/filter/decl.m4 @@ -53,7 +53,12 @@ m4_define(FID_LINE_IN, `m4_divert(107)') m4_define(FID_INTERPRET_BODY, `m4_divert(108)') m4_define(FID_ALL, `FID_INTERPRET_BODY'); -m4_define(FID_HIC, `m4_ifelse(TARGET, [[H]], $1, TARGET, [[I]], $2, TARGET, [[C]], $3)') +m4_define(FID_HIC, `m4_ifelse(TARGET, [[H]], [[$1]], TARGET, [[I]], [[$2]], TARGET, [[C]], [[$3]])') + +m4_define(FID_INTERPRET_EXEC, `FID_HIC(,[[FID_INTERPRET_BODY()]],[[m4_divert(-1)]])') +m4_define(FID_INTERPRET_NEW, `FID_HIC(,[[m4_divert(-1)]],[[FID_INTERPRET_BODY()]])') +m4_define(NEVER_CONSTANT, `m4_define([[INST_NEVER_CONSTANT]])') +m4_define(FID_IFCONST, `m4_ifdef([[INST_NEVER_CONSTANT]],[[$2]],[[$1]])') m4_define(INST_FLUSH, `m4_ifdef([[INST_NAME]], [[ FID_ENUM @@ -72,26 +77,29 @@ FID_NEW FID_HIC( [[ struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code -[[m4_undivert(102)]] +m4_undivert(102) );]], [[ case INST_NAME(): #define whati (&(what->i_]]INST_NAME()[[)) m4_ifelse(m4_eval(INST_INVAL() > 0), 1, [[if (fstk->vcnt < INST_INVAL()) runtime("Stack underflow"); fstk->vcnt -= INST_INVAL(); ]]) - [[m4_undivert(108)]] + m4_undivert(108) #undef whati break; ]], [[ struct f_inst *f_new_inst_]]INST_NAME()[[(enum f_instruction_code fi_code -[[m4_undivert(102)]] +m4_undivert(102) ) { struct f_inst *what = fi_new(fi_code); + FID_IFCONST([[uint constargs = 1;]]) #define whati (&(what->i_]]INST_NAME()[[)) - [[m4_undivert(103)]] + m4_undivert(103) + FID_IFCONST([[if (!constargs)]]) + return what; + FID_IFCONST([[m4_undivert(108)]]) #undef whati - return what; } ]]) @@ -130,13 +138,14 @@ m4_undivert(106) #undef f1 #undef f2 break; - +m4_divert(-1)FID_FLUSH(101,200) ]])') m4_define(INST, `m4_dnl INST_FLUSH()m4_dnl m4_define([[INST_NAME]], [[$1]])m4_dnl m4_define([[INST_INVAL]], [[$2]])m4_dnl +m4_undefine([[INST_NEVER_CONSTANT]])m4_dnl FID_ALL() m4_dnl ') @@ -149,22 +158,18 @@ FID_NEW_ARGS , $1 $2 FID_NEW_BODY whati->$2 = $2; -m4_ifelse($3,,,[[ FID_LINEARIZE_BODY -item->$3 = whati->$2; -]]) -m4_ifelse($4,,,[[ +item->$2 = whati->$2; +m4_ifelse($3,,,[[ FID_SAME_BODY -if ($4) return 0; +if ($3) return 0; ]]) -m4_ifelse($5,,,[[ +m4_ifelse($4,,,[[ FID_DUMP_BODY -debug("%s$5\n", INDENT, $6); -]]) -m4_ifelse($7,,,[[ -FID_INTERPRET_BODY -$7 +debug("%s$4\n", INDENT, $5); ]]) +FID_INTERPRET_EXEC +const $1 $2 = whati->$2 FID_ALL') m4_define(ARG_ANY, ` @@ -174,34 +179,39 @@ FID_NEW_ARGS , struct f_inst * f$1 FID_NEW_BODY whati->f$1 = f$1; -for (const struct f_inst *child = f$1; child; child = child->next) what->size += child->size; +for (const struct f_inst *child = f$1; child; child = child->next) { + what->size += child->size; +FID_IFCONST([[ + if (child->fi_code != FI_CONSTANT) + constargs = 0; +]]) +} FID_LINEARIZE_BODY -pos = linearize(dest, whati->f$1, pos);m4_dnl +pos = linearize(dest, whati->f$1, pos); FID_ALL()') m4_define(ARG, `ARG_ANY($1) -FID_INTERPRET_BODY +FID_INTERPRET_EXEC() if (v$1.type != $2) runtime("Argument $1 of instruction %s must be of type $2, got 0x%02x", f_instruction_name(what->fi_code), v$1.type)m4_dnl FID_ALL()') -m4_define(LINEX, `FID_INTERPRET_BODY -do { +m4_define(LINEX, `FID_INTERPRET_EXEC()LINEX_($1)FID_INTERPRET_NEW()return $1 FID_ALL()') +m4_define(LINEX_, `do { fstk->estk[fstk->ecnt].pos = 0; fstk->estk[fstk->ecnt].line = $1; fstk->estk[fstk->ecnt].ventry = fstk->vcnt; fstk->estk[fstk->ecnt].vbase = fstk->estk[fstk->ecnt-1].vbase; fstk->estk[fstk->ecnt].emask = 0; fstk->ecnt++; -} while (0)m4_dnl -FID_ALL()') +} while (0)') m4_define(LINE, ` FID_LINE_IN const struct f_line * fl$1; FID_STRUCT_IN -const struct f_inst * f$1; +struct f_inst * f$1; FID_NEW_ARGS -, const struct f_inst * f$1 +, struct f_inst * f$1 FID_NEW_BODY whati->f$1 = f$1; FID_DUMP_BODY @@ -210,23 +220,25 @@ FID_LINEARIZE_BODY item->fl$1 = f_linearize(whati->f$1); FID_SAME_BODY if (!f_same(f1->fl$1, f2->fl$1)) return 0; -FID_INTERPRET_BODY +FID_INTERPRET_EXEC do { if (whati->fl$1) { - LINEX(whati->fl$1); -} } while(0)m4_dnl + LINEX_(whati->fl$1); +} } while(0) +FID_INTERPRET_NEW +return whati->f$1 FID_ALL()') m4_define(RESULT, `RESULT_VAL([[ (struct f_val) { .type = $1, .val.$2 = $3 } ]])') -m4_define(RESULT_VAL, `FID_INTERPRET_BODY()do { res = $1; fstk->vcnt++; } while (0)FID_ALL()') +m4_define(RESULT_VAL, `FID_HIC(, [[do { res = $1; fstk->vcnt++; } while (0)]], +[[return fi_constant(what, $1)]])') m4_define(RESULT_VOID, `RESULT_VAL([[ (struct f_val) { .type = T_VOID } ]])') -m4_define(SYMBOL, `FID_MEMBER(const struct symbol *, sym, sym, -[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name, const struct symbol *sym = whati->sym)') -m4_define(FRET, `') -m4_define(ECS, `FID_MEMBER(enum ec_subtype, ecs, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs), enum ec_subtype ecs = whati->ecs)') -m4_define(RTC, `FID_MEMBER(const struct rtable_config *, rtc, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name, struct rtable *table = whati->rtc->table)') -m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa, sa, f1->sa.sa_code != f2->sa.sa_code,,, struct f_static_attr sa = whati->sa)') -m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da, da, f1->da.ea_code != f2->da.ea_code,,, struct f_dynamic_attr da = whati->da)') +m4_define(SYMBOL, `FID_MEMBER(struct symbol *, sym, +[[strcmp(f1->sym->name, f2->sym->name) || (f1->sym->class != f2->sym->class)]], symbol %s, item->sym->name)') +m4_define(RTC, `FID_MEMBER(struct rtable_config *, rtc, [[strcmp(f1->rtc->name, f2->rtc->name)]], route table %s, item->rtc->name)') +m4_define(STATIC_ATTR, `FID_MEMBER(struct f_static_attr, sa, f1->sa.sa_code != f2->sa.sa_code,,)') +m4_define(DYNAMIC_ATTR, `FID_MEMBER(struct f_dynamic_attr, da, f1->da.ea_code != f2->da.ea_code,,)') +m4_define(ACCESS_RTE, `NEVER_CONSTANT()') m4_define(FID_WR_PUT_LIST) m4_define(FID_WR_PUT_ALSO, `m4_define([[FID_WR_PUT_LIST]],FID_WR_PUT_LIST()[[FID_WR_DPUT(]]FID_WR_DIDX[[)FID_WR_DPUT(]]$1[[)]])m4_define([[FID_WR_DIDX]],m4_eval(FID_WR_DIDX+1))m4_divert(FID_WR_DIDX)') @@ -267,8 +279,25 @@ fi_new(enum f_instruction_code fi_code) return what; } +static inline struct f_inst * +fi_constant(struct f_inst *what, struct f_val val) +{ + what->fi_code = FI_CONSTANT; + what->i_FI_CONSTANT.val = val; + return what; +} + +#define v1 whati->f1->i_FI_CONSTANT.val +#define v2 whati->f2->i_FI_CONSTANT.val +#define v3 whati->f3->i_FI_CONSTANT.val +#define runtime(fmt, ...) cf_error("filter preevaluation, line %d: " fmt, ifs->lino, ##__VA_ARGS__) +#define fpool cfg_mem +#define falloc(size) cfg_alloc(size) /* Instruction constructors */ FID_WR_PUT(3) +#undef v1 +#undef v2 +#undef v3 /* Line dumpers */ #define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1) @@ -387,9 +416,9 @@ FID_WR_PUT(3) m4_divert(-1) m4_changequote(`,') -m4_define(FID_CLEANUP, `m4_ifelse($1,$2,,[[m4_undivert($1)FID_CLEANUP(m4_eval($1+1),$2)]])') +m4_define(FID_FLUSH, `m4_ifelse($1,$2,,[[m4_undivert($1)FID_FLUSH(m4_eval($1+1),$2)]])') m4_define(FID_WR_DPUT, `m4_undivert($1)') -m4_m4wrap(`INST_FLUSH()m4_divert(0)FID_WR_PUT_LIST()m4_divert(-1)FID_CLEANUP(1,200)') +m4_m4wrap(`INST_FLUSH()m4_divert(0)FID_WR_PUT_LIST()m4_divert(-1)FID_FLUSH(1,200)') m4_changequote([[,]]) diff --git a/filter/f-inst.c b/filter/f-inst.c index a70a4a92..edc97794 100644 --- a/filter/f-inst.c +++ b/filter/f-inst.c @@ -37,12 +37,10 @@ * * m4_dnl FID_MEMBER( custom instruction member * m4_dnl C type, for storage in structs - * m4_dnl name in f_inst, how the member is named before linearization - * m4_dnl name in f_line_item, how the member is named afterwards + * m4_dnl name, how the member is named * m4_dnl comparator for same(), if different, this should be TRUE (CAVEAT) * m4_dnl dump format string debug -> format string for bvsnprintf * m4_dnl dump format args appropriate args - * m4_dnl interpreter body how to deal with this on execution * m4_dnl ) * * m4_dnl RESULT(type, union-field, value); putting this on value stack @@ -106,7 +104,7 @@ ARG_ANY(1); ARG(2, T_INT); - FID_MEMBER(enum ec_subtype, ecs, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs), enum ec_subtype ecs = whati->ecs); + FID_MEMBER(enum ec_subtype, ecs, f1->ecs != f2->ecs, ec subtype %s, ec_subtype_str(item->ecs)); int check, ipv4_used; u32 key, val; @@ -152,24 +150,37 @@ INST(FI_PATHMASK_CONSTRUCT, 0, 1) { ARG_ANY(1); - FID_MEMBER(uint, count, count, f1->count != f2->count, number of items %u, item->count); + FID_MEMBER(uint, count, f1->count != f2->count, number of items %u, item->count); FID_NEW_BODY uint len = 0; - uint dyn = 0; - for (const struct f_inst *tt = f1; tt; tt = tt->next, len++) - if (tt->fi_code != FI_CONSTANT) - dyn++; + for (const struct f_inst *tt = f1; tt; tt = tt->next, len++); whati->count = len; + struct f_inst **items; + if (constargs) { + items = alloca(len * sizeof(struct f_inst *)); + for (uint i=0; f1; i++) { + items[i] = f1; + f1 = f1->next; + items[i]->next = 0; + } + whati->f1 = NULL; + } FID_ALL + FID_INTERPRET_EXEC if (fstk->vcnt < whati->count) /* TODO: make this check systematic */ runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count); - struct f_path_mask *pm = lp_alloc(fs->pool, sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item)); +#define pv fstk->vstk[fstk->vcnt - count + i] + + FID_INTERPRET_NEW +#define pv items[i]->i_FI_CONSTANT.val + + FID_INTERPRET_BODY + struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item)); for (uint i=0; icount; i++) { -#define pv fstk->vstk[fstk->vcnt - whati->count + i] switch (pv.type) { case T_PATH_MASK_ITEM: pm->item[i] = pv.val.pmi; @@ -185,9 +196,11 @@ } } - fstk->vcnt -= whati->count; - pm->len = whati->count; + FID_INTERPRET_EXEC + fstk->vcnt -= whati->count; + FID_ALL + pm->len = whati->count; RESULT(T_PATH_MASK, path_mask, pm); } @@ -270,8 +283,10 @@ /* Set to indirect value prepared in v1 */ INST(FI_VAR_SET, 1, 0) { + NEVER_CONSTANT; ARG_ANY(1); SYMBOL; + if ((sym->class != (SYM_VARIABLE | v1.type)) && (v1.type != T_VOID)) { /* IP->Quad implicit conversion */ @@ -289,6 +304,7 @@ INST(FI_VAR_GET, 0, 1) { SYMBOL; + NEVER_CONSTANT; RESULT_VAL(fstk->vstk[curline.vbase + sym->offset]); } @@ -297,26 +313,27 @@ FID_MEMBER( struct f_val, val, - val, [[ !val_same(&(f1->val), &(f2->val)) ]], value %s, val_dump(&(item->val)) ); - RESULT_VAL(whati->val); + RESULT_VAL(val); } INST(FI_PRINT, 1, 0) { + NEVER_CONSTANT; ARG_ANY(1); val_format(&(v1), &fs->buf); } INST(FI_CONDITION, 1, 0) { ARG(1, T_BOOL); - if (res.val.i) + if (v1.val.i) LINE(2,0); else LINE(3,1); } INST(FI_PRINT_AND_DIE, 0, 0) { + NEVER_CONSTANT; FID_LINEARIZE_BODY { uint opos = pos; @@ -330,7 +347,7 @@ } FID_ALL - FID_MEMBER(enum filter_return, fret, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret), enum filter_return fret = whati->fret); + FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret)); if ((fret == F_NOP || (fret != F_NONL && (what->flags & FIF_PRINTED))) && !(fs->flags & FF_SILENT)) @@ -663,7 +680,7 @@ runtime( "SADR expected" ); net_addr_ip6_sadr *net = (void *) v1.val.net; - net_addr *src = lp_alloc(fs->pool, sizeof(net_addr_ip6)); + net_addr *src = falloc(sizeof(net_addr_ip6)); net_fill_ip6(src, net->src_prefix, net->src_pxlen); RESULT(T_NET, net, src); @@ -721,6 +738,7 @@ } INST(FI_RETURN, 1, 1) { + NEVER_CONSTANT; /* Acquire the return value */ ARG_ANY(1); uint retpos = fstk->vcnt; @@ -748,6 +766,7 @@ } INST(FI_CALL, 0, 1) { + NEVER_CONSTANT; SYMBOL; /* Push the body on stack */ @@ -768,13 +787,14 @@ } INST(FI_DROP_RESULT, 1, 0) { + NEVER_CONSTANT; ARG_ANY(1); } INST(FI_SWITCH, 1, 0) { ARG_ANY(1); - FID_MEMBER(const struct f_tree *, tree, tree, [[!same_tree(f1->tree, f2->tree)]], tree %p, item->tree, const struct f_tree *tree = whati->tree); + FID_MEMBER(struct f_tree *, tree, [[!same_tree(f1->tree, f2->tree)]], tree %p, item->tree); const struct f_tree *t = find_tree(tree, &v1); if (!t) { @@ -782,7 +802,7 @@ t = find_tree(tree, &v1); if (!t) { debug( "No else statement?\n"); - break; + FID_HIC(,break,return NULL); } } /* It is actually possible to have t->data NULL */ @@ -801,7 +821,7 @@ INST(FI_PATH_PREPEND, 2, 1) { /* Path prepend */ ARG(1, T_PATH); ARG(2, T_INT); - RESULT(T_PATH, ad, [[ as_path_prepend(fs->pool, v1.val.ad, v2.val.i) ]]); + RESULT(T_PATH, ad, [[ as_path_prepend(fpool, v1.val.ad, v2.val.i) ]]); } INST(FI_CLIST_ADD, 2, 1) { /* (Extended) Community list add */ @@ -816,14 +836,14 @@ struct f_val dummy; if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) - RESULT(T_CLIST, ad, [[ int_set_add(fs->pool, v1.val.ad, v2.val.i) ]]); + RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, v2.val.i) ]]); /* IP->Quad implicit conversion */ else if (val_is_ip4(&v2)) - RESULT(T_CLIST, ad, [[ int_set_add(fs->pool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); + RESULT(T_CLIST, ad, [[ int_set_add(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy)) runtime("Can't add set"); else if (v2.type == T_CLIST) - RESULT(T_CLIST, ad, [[ int_set_union(fs->pool, v1.val.ad, v2.val.ad) ]]); + RESULT(T_CLIST, ad, [[ int_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else runtime("Can't add non-pair"); } @@ -834,11 +854,11 @@ if ((v2.type == T_SET) && eclist_set_type(v2.val.t)) runtime("Can't add set"); else if (v2.type == T_ECLIST) - RESULT(T_ECLIST, ad, [[ ec_set_union(fs->pool, v1.val.ad, v2.val.ad) ]]); + RESULT(T_ECLIST, ad, [[ ec_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else if (v2.type != T_EC) runtime("Can't add non-ec"); else - RESULT(T_ECLIST, ad, [[ ec_set_add(fs->pool, v1.val.ad, v2.val.ec) ]]); + RESULT(T_ECLIST, ad, [[ ec_set_add(fpool, v1.val.ad, v2.val.ec) ]]); } else if (v1.type == T_LCLIST) @@ -847,11 +867,11 @@ if ((v2.type == T_SET) && lclist_set_type(v2.val.t)) runtime("Can't add set"); else if (v2.type == T_LCLIST) - RESULT(T_LCLIST, ad, [[ lc_set_union(fs->pool, v1.val.ad, v2.val.ad) ]]); + RESULT(T_LCLIST, ad, [[ lc_set_union(fpool, v1.val.ad, v2.val.ad) ]]); else if (v2.type != T_LC) runtime("Can't add non-lc"); else - RESULT(T_LCLIST, ad, [[ lc_set_add(fs->pool, v1.val.ad, v2.val.lc) ]]); + RESULT(T_LCLIST, ad, [[ lc_set_add(fpool, v1.val.ad, v2.val.lc) ]]); } @@ -874,7 +894,7 @@ else runtime("Can't delete non-integer (set)"); - RESULT(T_PATH, ad, [[ as_path_filter(fs->pool, v1.val.ad, set, key, 0) ]]); + RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, set, key, 0) ]]); } else if (v1.type == T_CLIST) @@ -883,12 +903,12 @@ struct f_val dummy; if ((v2.type == T_PAIR) || (v2.type == T_QUAD)) - RESULT(T_CLIST, ad, [[ int_set_del(fs->pool, v1.val.ad, v2.val.i) ]]); + RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, v2.val.i) ]]); /* IP->Quad implicit conversion */ else if (val_is_ip4(&v2)) - RESULT(T_CLIST, ad, [[ int_set_del(fs->pool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); + RESULT(T_CLIST, ad, [[ int_set_del(fpool, v1.val.ad, ipa_to_u32(v2.val.ip)) ]]); else if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST)) - RESULT(T_CLIST, ad, [[ clist_filter(fs->pool, v1.val.ad, &v2, 0) ]]); + RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 0) ]]); else runtime("Can't delete non-pair"); } @@ -897,22 +917,22 @@ { /* v2.val is either EC or EC-set */ if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fs->pool, v1.val.ad, &v2, 0) ]]); + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 0) ]]); else if (v2.type != T_EC) runtime("Can't delete non-ec"); else - RESULT(T_ECLIST, ad, [[ ec_set_del(fs->pool, v1.val.ad, v2.val.ec) ]]); + RESULT(T_ECLIST, ad, [[ ec_set_del(fpool, v1.val.ad, v2.val.ec) ]]); } else if (v1.type == T_LCLIST) { /* v2.val is either LC or LC-set */ if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fs->pool, v1.val.ad, &v2, 0) ]]); + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 0) ]]); else if (v2.type != T_LC) runtime("Can't delete non-lc"); else - RESULT(T_LCLIST, ad, [[ lc_set_del(fs->pool, v1.val.ad, v2.val.lc) ]]); + RESULT(T_LCLIST, ad, [[ lc_set_del(fpool, v1.val.ad, v2.val.lc) ]]); } else @@ -927,7 +947,7 @@ u32 key = 0; if ((v2.type == T_SET) && (v2.val.t->from.type == T_INT)) - RESULT(T_PATH, ad, [[ as_path_filter(fs->pool, v1.val.ad, v2.val.t, key, 1) ]]); + RESULT(T_PATH, ad, [[ as_path_filter(fpool, v1.val.ad, v2.val.t, key, 1) ]]); else runtime("Can't filter integer"); } @@ -938,7 +958,7 @@ struct f_val dummy; if ((v2.type == T_SET) && clist_set_type(v2.val.t, &dummy) || (v2.type == T_CLIST)) - RESULT(T_CLIST, ad, [[ clist_filter(fs->pool, v1.val.ad, &v2, 1) ]]); + RESULT(T_CLIST, ad, [[ clist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter pair"); } @@ -947,7 +967,7 @@ { /* v2.val is either EC or EC-set */ if ((v2.type == T_SET) && eclist_set_type(v2.val.t) || (v2.type == T_ECLIST)) - RESULT(T_ECLIST, ad, [[ eclist_filter(fs->pool, v1.val.ad, &v2, 1) ]]); + RESULT(T_ECLIST, ad, [[ eclist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter ec"); } @@ -956,7 +976,7 @@ { /* v2.val is either LC or LC-set */ if ((v2.type == T_SET) && lclist_set_type(v2.val.t) || (v2.type == T_LCLIST)) - RESULT(T_LCLIST, ad, [[ lclist_filter(fs->pool, v1.val.ad, &v2, 1) ]]); + RESULT(T_LCLIST, ad, [[ lclist_filter(fpool, v1.val.ad, &v2, 1) ]]); else runtime("Can't filter lc"); } @@ -966,7 +986,9 @@ } INST(FI_ROA_CHECK_IMPLICIT, 0, 1) { /* ROA Check */ + NEVER_CONSTANT; RTC(1); + struct rtable *table = rtc->table; ACCESS_RTE; ACCESS_EATTRS; const net_addr *net = (*fs->rte)->net->n.addr; @@ -994,9 +1016,11 @@ } INST(FI_ROA_CHECK_EXPLICIT, 2, 1) { /* ROA Check */ + NEVER_CONSTANT; ARG(1, T_NET); ARG(2, T_INT); RTC(3); + struct rtable *table = rtc->table; u32 as = v2.val.i; @@ -1015,15 +1039,18 @@ INST(FI_FORMAT, 1, 0) { /* Format */ ARG_ANY(1); - RESULT(T_STRING, s, val_format_str(fs, &v1)); + RESULT(T_STRING, s, val_format_str(fpool, &v1)); } INST(FI_ASSERT, 1, 0) { /* Birdtest Assert */ + NEVER_CONSTANT; ARG(1, T_BOOL); - FID_MEMBER(const char *, s, s, [[strcmp(f1->s, f2->s)]], string \"%s\", item->s); + FID_MEMBER(char *, s, [[strcmp(f1->s, f2->s)]], string \"%s\", item->s); + + ASSERT(s); if (!bt_assert_hook) runtime("No bt_assert hook registered, can't assert"); - bt_assert_hook(res.val.i, what); + bt_assert_hook(v1.val.i, what); } diff --git a/filter/filter.c b/filter/filter.c index ee29522e..ed0b21bc 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -150,14 +150,6 @@ f_rta_cow(struct filter_state *fs) f_cache_eattrs(fs); } -static char * -val_format_str(struct filter_state *fs, struct f_val *v) { - buffer b; - LOG_BUFFER_INIT(b); - val_format(v, &b); - return lp_strdup(fs->pool, b.start); -} - static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; /** @@ -215,6 +207,9 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) return F_ERROR; \ } while(0) +#define falloc(size) lp_alloc(fs->pool, size) +#define fpool fs->pool + #define ACCESS_RTE do { if (!fs->rte) runtime("No route to access"); } while (0) #define ACCESS_EATTRS do { if (!fs->eattrs) f_cache_eattrs(fs); } while (0) @@ -224,6 +219,8 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val) #undef v2 #undef v3 #undef runtime +#undef falloc +#undef fpool #undef ACCESS_RTE #undef ACCESS_EATTRS } diff --git a/lib/resource.h b/lib/resource.h index d9d4bb8f..ad17d9ed 100644 --- a/lib/resource.h +++ b/lib/resource.h @@ -101,9 +101,13 @@ void buffer_realloc(void **buf, unsigned *size, unsigned need, unsigned item_siz */ #define DMALLOC_DISABLE #include -#define xmalloc(size) _xmalloc_leap(__FILE__, __LINE__, size) -#define xrealloc(size) _xrealloc_leap(__FILE__, __LINE__, size) -#define xfree(ptr) _xfree_leap(__FILE__, __LINE__, ptr) +#define xmalloc(size) \ + dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 1) +#define xrealloc(ptr, size) \ + dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 1) +#define xfree(ptr) \ + dmalloc_free(__FILE__, __LINE__, (ptr), DMALLOC_FUNC_FREE) + #else /* * Unfortunately, several libraries we might want to link to define -- cgit v1.2.3