diff options
Diffstat (limited to 'nest')
-rw-r--r-- | nest/cli.h | 9 | ||||
-rw-r--r-- | nest/config.Y | 46 | ||||
-rw-r--r-- | nest/proto.c | 258 | ||||
-rw-r--r-- | nest/protocol.h | 31 |
4 files changed, 187 insertions, 157 deletions
@@ -33,6 +33,7 @@ typedef struct cli { void (*cleanup)(struct cli *c); void *rover; /* Private to continuation routine */ int last_reply; + int restricted; /* CLI is restricted to read-only commands */ struct linpool *parser_pool; /* Pool used during parsing */ byte *ring_buf; /* Ring buffer for asynchronous messages */ byte *ring_end, *ring_read, *ring_write; /* Pointers to the ring buffer */ @@ -60,6 +61,14 @@ void cli_kick(cli *); void cli_written(cli *); void cli_echo(unsigned int class, byte *msg); +static inline int cli_access_restricted(void) +{ + if (this_cli && this_cli->restricted) + return (cli_printf(this_cli, 8007, "Access denied"), 1); + else + return 0; +} + /* Functions provided by sysdep layer */ void cli_write_trigger(cli *); diff --git a/nest/config.Y b/nest/config.Y index 11f0a9b..5a89505 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -45,7 +45,7 @@ CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILT CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE) CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION) -CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES) +CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT) CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE) @@ -59,7 +59,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT) %type <s> optsym %type <ra> r_args %type <i> echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_or_preexport -%type <t> proto_patt +%type <ps> proto_patt proto_patt2 CF_GRAMMAR @@ -324,11 +324,11 @@ CF_CLI_HELP(SHOW, ..., [[Show status information]]) CF_CLI(SHOW STATUS,,, [[Show router status]]) { cmd_show_status(); } ; -CF_CLI(SHOW PROTOCOLS, optsym, [<name>], [[Show routing protocols]]) -{ proto_show($3, 0); } ; +CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]]) +{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ; -CF_CLI(SHOW PROTOCOLS ALL, optsym, [<name>], [[Show routing protocol details]]) -{ proto_show($4, 1); } ; +CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocol details]]) +{ proto_apply_cmd($4, proto_cmd_show, 0, 1); } ; optsym: SYM @@ -459,34 +459,42 @@ echo_size: ; CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]]) -{ proto_xxable($2, XX_DISABLE); } ; +{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ; CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]]) -{ proto_xxable($2, XX_ENABLE); } ; +{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ; CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]]) -{ proto_xxable($2, XX_RESTART); } ; +{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ; CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]]) -{ proto_xxable($2, XX_RELOAD); } ; +{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ; CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]]) -{ proto_xxable($3, XX_RELOAD_IN); } ; +{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ; CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]]) -{ proto_xxable($3, XX_RELOAD_OUT); } ; +{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ; CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]]) CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging via BIRD logs]]) -{ proto_debug($2, 0, $3); } - ; +{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ; CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]]) CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]]) -{ proto_debug($2, 1, $3); } - ; +{ proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ; + +CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]]) +{ this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ; proto_patt: - SYM { $$ = $1->name; } - | ALL { $$ = "*"; } - | TEXT + SYM { $$.ptr = $1; $$.patt = 0; } + | ALL { $$.ptr = NULL; $$.patt = 1; } + | TEXT { $$.ptr = $1; $$.patt = 1; } ; +proto_patt2: + SYM { $$.ptr = $1; $$.patt = 0; } + | { $$.ptr = NULL; $$.patt = 1; } + | TEXT { $$.ptr = $1; $$.patt = 1; } + ; + + CF_CODE CF_END diff --git a/nest/proto.c b/nest/proto.c index 57c2aa1..e9cf3df 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -25,12 +25,6 @@ static pool *proto_pool; static list protocol_list; static list proto_list; -#define WALK_PROTO_LIST(p) do { \ - node *nn; \ - WALK_LIST(nn, proto_list) { \ - struct proto *p = SKIP_BACK(struct proto, glob_node, nn); -#define WALK_PROTO_LIST_END } } while(0) - #define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0) list active_proto_list; @@ -847,11 +841,15 @@ proto_do_show_pipe_stats(struct proto *p) s1->imp_withdraws_ignored, s1->imp_withdraws_accepted); } -static void -proto_do_show(struct proto *p, int verbose) +void +proto_cmd_show(struct proto *p, unsigned int verbose, int cnt) { byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE]; + /* First protocol - show header */ + if (!cnt) + cli_msg(-2002, "name proto table state since info"); + buf[0] = 0; if (p->proto->get_status) p->proto->get_status(p, buf); @@ -886,25 +884,140 @@ proto_do_show(struct proto *p, int verbose) } void -proto_show(struct symbol *s, int verbose) +proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED) { - if (s && s->class != SYM_PROTO) + if (p->disabled) { - cli_msg(9002, "%s is not a protocol", s->name); + cli_msg(-8, "%s: already disabled", p->name); return; } - cli_msg(-2002, "name proto table state since info"); - if (s) - proto_do_show(((struct proto_config *)s->def)->proto, verbose); - else + + log(L_INFO "Disabling protocol %s", p->name); + p->disabled = 1; + proto_rethink_goal(p); + cli_msg(-9, "%s: disabled", p->name); +} + +void +proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED) +{ + if (!p->disabled) + { + cli_msg(-10, "%s: already enabled", p->name); + return; + } + + log(L_INFO "Enabling protocol %s", p->name); + p->disabled = 0; + proto_rethink_goal(p); + cli_msg(-11, "%s: enabled", p->name); +} + +void +proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED) +{ + if (p->disabled) + { + cli_msg(-8, "%s: already disabled", p->name); + return; + } + + log(L_INFO "Restarting protocol %s", p->name); + p->disabled = 1; + proto_rethink_goal(p); + p->disabled = 0; + proto_rethink_goal(p); + cli_msg(-12, "%s: restarted", p->name); +} + +void +proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED) +{ + if (p->disabled) + { + cli_msg(-8, "%s: already disabled", p->name); + return; + } + + /* If the protocol in not UP, it has no routes */ + if (p->proto_state != PS_UP) + return; + + log(L_INFO "Reloading protocol %s", p->name); + + /* re-importing routes */ + if (dir != CMD_RELOAD_OUT) + if (! (p->reload_routes && p->reload_routes(p))) + { + cli_msg(-8006, "%s: reload failed", p->name); + return; + } + + /* re-exporting routes */ + if (dir != CMD_RELOAD_IN) + proto_request_feeding(p); + + cli_msg(-15, "%s: reloading", p->name); +} + +void +proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED) +{ + p->debug = mask; +} + +void +proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED) +{ + p->mrtdump = mask; +} + +static void +proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg) +{ + if (s->class != SYM_PROTO) { - WALK_PROTO_LIST(p) - proto_do_show(p, verbose); - WALK_PROTO_LIST_END; + cli_msg(9002, "%s is not a protocol", s->name); + return; } + + cmd(((struct proto_config *)s->def)->proto, arg, 0); cli_msg(0, ""); } +static void +proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg) +{ + int cnt = 0; + + node *nn; + WALK_LIST(nn, proto_list) + { + struct proto *p = SKIP_BACK(struct proto, glob_node, nn); + + if (!patt || patmatch(patt, p->name)) + cmd(p, arg, cnt++); + } + + if (!cnt) + cli_msg(8003, "No protocols match"); + else + cli_msg(0, ""); +} + +void +proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), + int restricted, unsigned int arg) +{ + if (restricted && cli_access_restricted()) + return; + + if (ps.patt) + proto_apply_cmd_patt(ps.ptr, cmd, arg); + else + proto_apply_cmd_symbol(ps.ptr, cmd, arg); +} + struct proto * proto_get_named(struct symbol *sym, struct protocol *pr) { @@ -933,112 +1046,3 @@ proto_get_named(struct symbol *sym, struct protocol *pr) } return p; } - -void -proto_xxable(char *pattern, int xx) -{ - int cnt = 0; - WALK_PROTO_LIST(p) - if (patmatch(pattern, p->name)) - { - cnt++; - switch (xx) - { - case XX_DISABLE: - if (p->disabled) - cli_msg(-8, "%s: already disabled", p->name); - else - { - log(L_INFO "Disabling protocol %s", p->name); - p->disabled = 1; - proto_rethink_goal(p); - cli_msg(-9, "%s: disabled", p->name); - } - break; - - case XX_ENABLE: - if (!p->disabled) - cli_msg(-10, "%s: already enabled", p->name); - else - { - log(L_INFO "Enabling protocol %s", p->name); - p->disabled = 0; - proto_rethink_goal(p); - cli_msg(-11, "%s: enabled", p->name); - } - break; - - case XX_RESTART: - if (p->disabled) - cli_msg(-8, "%s: already disabled", p->name); - else - { - log(L_INFO "Restarting protocol %s", p->name); - p->disabled = 1; - proto_rethink_goal(p); - p->disabled = 0; - proto_rethink_goal(p); - cli_msg(-12, "%s: restarted", p->name); - } - break; - - case XX_RELOAD: - case XX_RELOAD_IN: - case XX_RELOAD_OUT: - if (p->disabled) - { - cli_msg(-8, "%s: already disabled", p->name); - break; - } - - /* If the protocol in not UP, it has no routes */ - if (p->proto_state != PS_UP) - break; - - log(L_INFO "Reloading protocol %s", p->name); - - /* re-importing routes */ - if (xx != XX_RELOAD_OUT) - if (! (p->reload_routes && p->reload_routes(p))) - { - cli_msg(-8006, "%s: reload failed", p->name); - break; - } - - /* re-exporting routes */ - if (xx != XX_RELOAD_IN) - proto_request_feeding(p); - - cli_msg(-15, "%s: reloading", p->name); - break; - - default: - ASSERT(0); - } - } - WALK_PROTO_LIST_END; - if (!cnt) - cli_msg(8003, "No protocols match"); - else - cli_msg(0, ""); -} - -void -proto_debug(char *pattern, int which, unsigned int mask) -{ - int cnt = 0; - WALK_PROTO_LIST(p) - if (patmatch(pattern, p->name)) - { - cnt++; - if (which == 0) - p->debug = mask; - else - p->mrtdump = mask; - } - WALK_PROTO_LIST_END; - if (!cnt) - cli_msg(8003, "No protocols match"); - else - cli_msg(0, ""); -} diff --git a/nest/protocol.h b/nest/protocol.h index 82f3766..99356a3 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -195,21 +195,30 @@ struct proto { /* Hic sunt protocol-specific data */ }; +struct proto_spec { + void *ptr; + int patt; +}; + + void *proto_new(struct proto_config *, unsigned size); void *proto_config_new(struct protocol *, unsigned size); - void proto_request_feeding(struct proto *p); -void proto_show(struct symbol *, int); + +void proto_cmd_show(struct proto *, unsigned int, int); +void proto_cmd_disable(struct proto *, unsigned int, int); +void proto_cmd_enable(struct proto *, unsigned int, int); +void proto_cmd_restart(struct proto *, unsigned int, int); +void proto_cmd_reload(struct proto *, unsigned int, int); +void proto_cmd_debug(struct proto *, unsigned int, int); +void proto_cmd_mrtdump(struct proto *, unsigned int, int); + +void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), int restricted, unsigned int arg); struct proto *proto_get_named(struct symbol *, struct protocol *); -void proto_xxable(char *, int); -void proto_debug(char *, int, unsigned int); - -#define XX_DISABLE 0 -#define XX_ENABLE 1 -#define XX_RESTART 2 -#define XX_RELOAD 3 -#define XX_RELOAD_IN 4 -#define XX_RELOAD_OUT 5 + +#define CMD_RELOAD 0 +#define CMD_RELOAD_IN 1 +#define CMD_RELOAD_OUT 2 static inline u32 proto_get_router_id(struct proto_config *pc) |