diff options
-rw-r--r-- | doc/bird.sgml | 16 | ||||
-rw-r--r-- | doc/reply_codes | 2 | ||||
-rw-r--r-- | filter/filter.c | 32 | ||||
-rw-r--r-- | filter/filter.h | 3 | ||||
-rw-r--r-- | nest/cmds.c | 20 | ||||
-rw-r--r-- | nest/cmds.h | 3 | ||||
-rw-r--r-- | nest/config.Y | 8 | ||||
-rw-r--r-- | sysdep/unix/log.c | 2 |
8 files changed, 70 insertions, 16 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 27f8b869..a1d3dc2c 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -282,7 +282,7 @@ protocol rip { <tag>include "<m/filename/"</tag> This statement causes inclusion of a new file. The maximal depth is set to 5. - <tag>log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> + <tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag> Set logging of messages having the given class (either <cf/all/ or <cf/{ error, trace }/ etc.) into selected destination (a file specified as a filename string, syslog with optional name argument, or the stderr output). Classes are: @@ -651,9 +651,6 @@ This argument can be omitted if there exists only a single instance. <p>Here is a brief list of supported functions: <descrip> - <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag> - Dump contents of internal data structures to the debugging output. - <tag>show status</tag> Show router status, that is BIRD version, uptime and time from last reconfiguration. @@ -812,6 +809,17 @@ This argument can be omitted if there exists only a single instance. <tag>debug <m/protocol/|<m/pattern/|all all|off|{ states | routes | filters | events | packets }</tag> Control protocol debugging. + + <tag>dump resources|sockets|interfaces|neighbors|attributes|routes|protocols</tag> + Dump contents of internal data structures to the debugging output. + + <tag>echo all|off|{ <m/list of log classes/ } [ <m/buffer-size/ ]</tag> + Control echoing of log messages to the command-line output. + See <ref id="dsc-log" name="log option"> for a list of log classes. + + <tag>eval <m/expr/</tag> + Evaluate given expression. + </descrip> <chapt>Filters diff --git a/doc/reply_codes b/doc/reply_codes index 58807241..e9996eef 100644 --- a/doc/reply_codes +++ b/doc/reply_codes @@ -31,6 +31,7 @@ Reply codes of BIRD command-line interface 0020 Configuration OK 0021 Undo requested 0022 Undo scheduled +0023 Evaluation of expression 1000 BIRD version 1001 Interface list @@ -61,6 +62,7 @@ Reply codes of BIRD command-line interface 8005 Protocol is down => cannot dump 8006 Reload failed 8007 Access denied +8008 Evaluation runtime error 9000 Command too long 9001 Parse error diff --git a/filter/filter.c b/filter/filter.c index 432fa122..d784c253 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -440,8 +440,6 @@ val_in_range(struct f_val v1, struct f_val v2) return CMP_ERROR; } -static void val_print(struct f_val v); - static void tree_node_print(struct f_tree *t, char **sep) { @@ -474,7 +472,7 @@ tree_print(struct f_tree *t) /* * val_print - format filter value */ -static void +void val_print(struct f_val v) { char buf2[1024]; @@ -558,6 +556,8 @@ static struct rate_limit rl_runtime_err; #define TWOARGS_C TWOARGS \ if (v1.type != v2.type) \ runtime( "Can't operate with values of incompatible types" ); +#define ACCESS_RTE \ + do { if (!f_rte) runtime("No route to access"); } while (0) /** * interpret @@ -821,6 +821,7 @@ interpret(struct f_inst *what) break; case 'a': /* rta access */ { + ACCESS_RTE; struct rta *rta = (*f_rte)->attrs; res.type = what->aux; switch(res.type) { @@ -845,6 +846,7 @@ interpret(struct f_inst *what) } break; case P('a','S'): + ACCESS_RTE; ONEARG; if (what->aux != v1.type) runtime( "Attempt to set static attribute to incompatible type" ); @@ -877,6 +879,7 @@ interpret(struct f_inst *what) } break; case P('e','a'): /* Access to extended attributes */ + ACCESS_RTE; { eattr *e = NULL; if (!(f_flags & FF_FORCE_TMPATTR)) @@ -944,6 +947,7 @@ interpret(struct f_inst *what) } break; case P('e','S'): + ACCESS_RTE; ONEARG; { struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr)); @@ -1021,10 +1025,12 @@ interpret(struct f_inst *what) } break; case 'P': + ACCESS_RTE; res.type = T_INT; res.val.i = (*f_rte)->pref; break; case P('P','S'): + ACCESS_RTE; ONEARG; if (v1.type != T_INT) runtime( "Can't set preference to non-integer" ); @@ -1246,6 +1252,7 @@ interpret(struct f_inst *what) } else { + ACCESS_RTE; v1.val.px.ip = (*f_rte)->net->n.prefix; v1.val.px.len = (*f_rte)->net->n.pxlen; @@ -1478,22 +1485,27 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc return res.val.i; } -int -f_eval_int(struct f_inst *expr) +struct f_val +f_eval(struct f_inst *expr, struct linpool *tmp_pool) { - /* Called independently in parse-time to eval expressions */ - struct f_val res; - f_flags = 0; f_tmp_attrs = NULL; f_rte = NULL; - f_pool = cfg_mem; + f_pool = tmp_pool; log_reset(); - res = interpret(expr); + return interpret(expr); +} + +int +f_eval_int(struct f_inst *expr) +{ + /* Called independently in parse-time to eval expressions */ + struct f_val res = f_eval(expr, cfg_mem); if (res.type != T_INT) cf_error("Integer expression expected"); + return res.val.i; } diff --git a/filter/filter.h b/filter/filter.h index 2386fc95..1d5150e7 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -106,6 +106,7 @@ struct ea_list; struct rte; int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags); +struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool); int f_eval_int(struct f_inst *expr); u32 f_eval_asn(struct f_inst *expr); @@ -117,6 +118,8 @@ int i_same(struct f_inst *f1, struct f_inst *f2); int val_compare(struct f_val v1, struct f_val v2); int tree_compare(const void *p1, const void *p2); +void val_print(struct f_val v); + #define F_NOP 0 #define F_NONL 1 #define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */ diff --git a/nest/cmds.c b/nest/cmds.c index 54ace169..9bdd66cd 100644 --- a/nest/cmds.c +++ b/nest/cmds.c @@ -13,6 +13,7 @@ #include "nest/cmds.h" #include "lib/string.h" #include "lib/resource.h" +#include "filter/filter.h" extern int shutting_down; extern int configuring; @@ -90,3 +91,22 @@ cmd_show_memory(void) print_size("Total:", rmemsize(&root_pool)); cli_msg(0, ""); } + +extern const char *log_buffer_ptr; + +void +cmd_eval(struct f_inst *expr) +{ + struct f_val v = f_eval(expr, this_cli->parser_pool); + log_reset(); + + if (v.type == T_RETURN) + { + cli_msg(8008, "runtime error"); + return; + } + + val_print(v); + cli_msg(23, "%s", log_buffer_ptr); + log_reset(); +} diff --git a/nest/cmds.h b/nest/cmds.h index 8b0bff7e..4cf8fb1b 100644 --- a/nest/cmds.h +++ b/nest/cmds.h @@ -11,6 +11,9 @@ struct sym_show_data { struct symbol *sym; }; +struct f_inst; + void cmd_show_status(void); void cmd_show_symbols(struct sym_show_data *sym); void cmd_show_memory(void); +void cmd_eval(struct f_inst *expr); diff --git a/nest/config.Y b/nest/config.Y index b85a5733..a6f13808 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -612,7 +612,11 @@ CF_CLI(DUMP ROUTES,,, [[Dump routing table]]) CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]]) { protos_dump_all(); cli_msg(0, ""); } ; -CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Configure echoing of log messages]]) { +CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]]) +{ cmd_eval($2); } ; + +CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]]) +CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) { cli_set_log_echo(this_cli, $2, $3); cli_msg(0, ""); } ; @@ -620,7 +624,7 @@ CF_CLI(ECHO, echo_mask echo_size, [all | off | <mask>] [<buffer-size>], [[Config echo_mask: ALL { $$ = ~0; } | OFF { $$ = 0; } - | NUM + | '{' log_mask_list '}' { $$ = $2; } ; echo_size: diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c index 92f12f1e..f3a66f8b 100644 --- a/sysdep/unix/log.c +++ b/sysdep/unix/log.c @@ -70,6 +70,8 @@ static char log_buffer[LOG_BUFFER_SIZE]; static char *log_buffer_pos; static int log_buffer_remains; +const char *log_buffer_ptr = log_buffer; + /** * log_reset - reset the log buffer |