Revision e0a45fb4

View differences:

client/client.c
25 25
#include "client/client.h"
26 26
#include "sysdep/unix/unix.h"
27 27

  
28
static char *opt_list = "s:v";
28
static char *opt_list = "s:vr";
29 29
static int verbose;
30
static char *init_cmd;
31
static int once;
30 32

  
31 33
static char *server_path = PATH_CONTROL_SOCKET;
32 34
static int server_fd;
......
49 51
static void
50 52
usage(void)
51 53
{
52
  fprintf(stderr, "Usage: birdc [-s <control-socket>] [-v]\n");
54
  fprintf(stderr, "Usage: birdc [-s <control-socket>] [-v] [-r]\n");
53 55
  exit(1);
54 56
}
55 57

  
......
67 69
      case 'v':
68 70
	verbose++;
69 71
	break;
72
      case 'r':
73
	init_cmd = "restrict";
74
	break;
70 75
      default:
71 76
	usage();
72 77
      }
78

  
79
  /* If some arguments are not options, we take it as commands */
73 80
  if (optind < argc)
74
    usage();
81
    {
82
      char *tmp;
83
      int i;
84
      int len = 0;
85

  
86
      if (init_cmd)
87
	usage();
88

  
89
      for (i = optind; i < argc; i++)
90
	len += strlen(argv[i]) + 1;
91

  
92
      tmp = init_cmd = malloc(len);
93
      for (i = optind; i < argc; i++)
94
	{
95
	  strcpy(tmp, argv[i]);
96
	  tmp += strlen(tmp);
97
	  *tmp++ = ' ';
98
	}
99

  
100
      once = 1;
101
    }
75 102
}
76 103

  
77 104
/*** Input ***/
......
267 294
  if (nstate == cstate)
268 295
    return;
269 296

  
297
  if (init_cmd)
298
    {
299
      /* First transition - client received hello from BIRD
300
	 and there is waiting initial command */
301
      submit_server_command(init_cmd);
302
      init_cmd = NULL;
303
      return;
304
    }
305

  
306
  if (!init_cmd && once)
307
    {
308
      /* Initial command is finished and we want to exit */
309
      cleanup();
310
      exit(0);
311
    }
312

  
270 313
  if (nstate == STATE_PROMPT)
271 314
    if (input_initialized)
272 315
      input_reveal();
doc/reply_codes
24 24
0013	Status report
25 25
0014	Route count
26 26
0015	Reloading
27
0016	Access restricted
27 28

  
28 29
1000	BIRD version
29 30
1001	Interface list
......
51 52
8004	Stopped due to reconfiguration
52 53
8005	Protocol is down => cannot dump
53 54
8006	Reload failed
55
8007	Access denied
54 56

  
55 57
9000	Command too long
56 58
9001	Parse error
nest/cli.h
33 33
  void (*cleanup)(struct cli *c);
34 34
  void *rover;				/* Private to continuation routine */
35 35
  int last_reply;
36
  int restricted;			/* CLI is restricted to read-only commands */
36 37
  struct linpool *parser_pool;		/* Pool used during parsing */
37 38
  byte *ring_buf;			/* Ring buffer for asynchronous messages */
38 39
  byte *ring_end, *ring_read, *ring_write;	/* Pointers to the ring buffer */
......
60 61
void cli_written(cli *);
61 62
void cli_echo(unsigned int class, byte *msg);
62 63

  
64
static inline int cli_access_restricted(void)
65
{
66
  if (this_cli && this_cli->restricted)
67
    return (cli_printf(this_cli, 8007, "Access denied"), 1);
68
  else
69
    return 0;
70
}
71

  
63 72
/* Functions provided by sysdep layer */
64 73

  
65 74
void cli_write_trigger(cli *);
nest/config.Y
45 45
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
46 46
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, GENERATE)
47 47
CF_KEYWORDS(LISTEN, BGP, V6ONLY, ADDRESS, PORT, PASSWORDS, DESCRIPTION)
48
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES)
48
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT)
49 49

  
50 50
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
51 51
	RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
......
325 325
{ cmd_show_status(); } ;
326 326

  
327 327
CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
328
{ proto_apply_cmd($3, proto_cmd_show, 0); } ;
328
{ proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
329 329

  
330 330
CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocol details]])
331
{ proto_apply_cmd($4, proto_cmd_show, 1); } ;
331
{ proto_apply_cmd($4, proto_cmd_show, 0, 1); } ;
332 332

  
333 333
optsym:
334 334
   SYM
......
459 459
 ;
460 460

  
461 461
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
462
{ proto_apply_cmd($2, proto_cmd_disable, 0); } ;
462
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
463 463
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
464
{ proto_apply_cmd($2, proto_cmd_enable, 0); } ;
464
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
465 465
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
466
{ proto_apply_cmd($2, proto_cmd_restart, 0); } ;
466
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
467 467
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
468
{ proto_apply_cmd($2, proto_cmd_reload, CMD_RELOAD); } ;
468
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
469 469
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
470
{ proto_apply_cmd($3, proto_cmd_reload, CMD_RELOAD_IN); } ;
470
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
471 471
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
472
{ proto_apply_cmd($3, proto_cmd_reload, CMD_RELOAD_OUT); } ;
472
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
473 473

  
474 474
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
475 475
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | events | packets }), [[Control protocol debugging via BIRD logs]])
476
{ proto_apply_cmd($2, proto_cmd_debug, $3); } ;
476
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
477 477

  
478 478
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
479 479
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]])
480
{ proto_apply_cmd($2, proto_cmd_mrtdump, $3); } ;
480
{ proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ;
481

  
482
CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]])
483
{ this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ;
481 484

  
482 485
proto_patt:
483 486
   SYM  { $$.ptr = $1; $$.patt = 0; }
nest/proto.c
1006 1006
}
1007 1007

  
1008 1008
void
1009
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1009
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int),
1010
		int restricted, unsigned int arg)
1010 1011
{
1012
  if (restricted && cli_access_restricted())
1013
    return;
1014

  
1011 1015
  if (ps.patt)
1012 1016
    proto_apply_cmd_patt(ps.ptr, cmd, arg);
1013 1017
  else
nest/protocol.h
213 213
void proto_cmd_debug(struct proto *, unsigned int, int);
214 214
void proto_cmd_mrtdump(struct proto *, unsigned int, int);
215 215

  
216
void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg);
216
void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), int restricted, unsigned int arg);
217 217
struct proto *proto_get_named(struct symbol *, struct protocol *);
218 218

  
219 219
#define CMD_RELOAD	0
sysdep/unix/config.Y
107 107
{ cmd_reconfig($3, RECONFIG_SOFT); } ;
108 108

  
109 109
CF_CLI(DOWN,,, [[Shut the daemon down]])
110
{ cli_msg(7, "Shutdown requested"); order_shutdown(); } ;
110
{ cmd_shutdown(); } ;
111 111

  
112 112
cfg_name:
113 113
   /* empty */ { $$ = NULL; }
sysdep/unix/main.c
141 141
{
142 142
  struct config *conf;
143 143

  
144
  if (cli_access_restricted())
145
    return;
146

  
144 147
  if (!name)
145 148
    name = config_name;
146 149
  cli_msg(-2, "Reading configuration from %s", name);
......
304 307
 */
305 308

  
306 309
void
310
cmd_shutdown(void)
311
{
312
  if (cli_access_restricted())
313
    return;
314

  
315
  cli_msg(7, "Shutdown requested");
316
  order_shutdown();
317
}
318

  
319
void
307 320
async_shutdown(void)
308 321
{
309 322
  DBG("Shutting down...\n");

Also available in: Unified diff