summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/cli.h9
-rw-r--r--nest/config.Y46
-rw-r--r--nest/proto.c258
-rw-r--r--nest/protocol.h31
4 files changed, 187 insertions, 157 deletions
diff --git a/nest/cli.h b/nest/cli.h
index f816ef18..57414a29 100644
--- a/nest/cli.h
+++ b/nest/cli.h
@@ -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 11f0a9b2..5a895051 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 57c2aa13..e9cf3dfa 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 82f3766f..99356a3d 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)