config.Y 19.4 KB
Newer Older
1 2 3
/*
 *	BIRD -- Core Configuration
 *
4
 *	(c) 1998--2000 Martin Mares <mj@ucw.cz>
5
 *      (c) 2004       Ondrej Filip <feela@network.cz>
6 7 8 9 10 11
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

CF_HDR

12
#include "nest/rt-dev.h"
13
#include "nest/password.h"
14
#include "nest/cmds.h"
15
#include "lib/lists.h"
16
#include "lib/mac.h"
17

18 19 20
CF_DEFINES

static struct proto_config *this_proto;
21
static struct channel_config *this_channel;
22
static struct iface_patt *this_ipatt;
23
static struct iface_patt_node *this_ipn;
Jan Moskyto Matejka's avatar
Jan Moskyto Matejka committed
24
/* static struct roa_table_config *this_roa_table; */
25 26
static list *this_p_list;
static struct password_item *this_p_item;
27 28
static int password_id;

29 30 31 32 33 34
static void
iface_patt_check(void)
{
  struct iface_patt_node *pn;

  WALK_LIST(pn, this_ipatt->ipn_list)
35
    if (!pn->pattern || pn->prefix.type)
36 37 38 39
      cf_error("Interface name/mask expected, not IP prefix");
}


40 41 42
static inline void
reset_passwords(void)
{
43
  this_p_list = NULL;
44 45 46
}

static inline list *
47 48 49 50 51 52 53
get_passwords(void)
{
  list *rv = this_p_list;
  this_p_list = NULL;
  return rv;
}

54 55 56 57 58 59 60 61 62
static void
proto_postconfig(void)
{
  CALL(this_proto->protocol->postconfig, this_proto);
  this_channel = NULL;
  this_proto = NULL;
}


63
#define DIRECT_CFG ((struct rt_dev_config *) this_proto)
64

65 66
CF_DECLS

67
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
68
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
69
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6)
70
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
71
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
72
CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
73
CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
74
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
75
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
76
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
77

78
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
79
	RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
80
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
81
CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
82
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
83

84
%type <i32> idval
85
%type <f> imexport
86
%type <r> rtable
87
%type <s> optsym
88
%type <ra> r_args
89
%type <sd> sym_args
90
%type <i> 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
91
%type <ps> proto_patt proto_patt2
92 93
%type <cc> channel_start proto_channel
%type <cl> limit_spec
94 95 96

CF_GRAMMAR

97 98
/* Setting of router ID */

99
CF_ADDTO(conf, rtrid)
100

101
rtrid:
102 103
   ROUTER ID idval ';' { new_config->router_id = $3; }
 | ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; }
104 105 106
 ;

idval:
107
   NUM { $$ = $1; }
108
 | '(' term ')' { $$ = f_eval_int($2); }
109
 | IP4 { $$ = ip4_to_u32($1); }
110 111 112
 | SYM {
     if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
       $$ = SYM_VAL($1).i;
113 114
     else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip))
       $$ = ipa_to_u32(SYM_VAL($1).ip);
115
     else
116
       cf_error("Number or IPv4 address constant expected");
117
   }
118 119
 ;

120

121
CF_ADDTO(conf, listen)
122

123
listen: LISTEN BGP listen_opts ';' ;
124

125
listen_opts:
126
   /* Nothing */
127
 | listen_opts listen_opt
128 129
 ;

130
listen_opt:
131 132
   ADDRESS ipa { new_config->listen_bgp_addr = $2; }
 | PORT expr { new_config->listen_bgp_port = $2; }
133 134
 | V6ONLY { new_config->listen_bgp_flags = 0; }
 | DUAL { new_config->listen_bgp_flags = 1; }
135 136 137
 ;


138 139 140 141 142
CF_ADDTO(conf, gr_opts)

gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;


143
/* Network types (for tables, channels) */
144

145 146
net_type:
   IPV4 { $$ = NET_IP4; }
147
 | IPV6 { $$ = NET_IP6; }
148 149
 | VPN4 { $$ = NET_VPN4; }
 | VPN6 { $$ = NET_VPN6; }
150 151
 | ROA4 { $$ = NET_ROA4; }
 | ROA6 { $$ = NET_ROA6; }
152 153
 | FLOW4{ $$ = NET_FLOW4; }
 | FLOW6{ $$ = NET_FLOW6; }
154 155
 ;

156 157
CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6)

158 159 160 161 162

/* Creation of routing tables */

CF_ADDTO(conf, table)

163
table_sorted:
164 165 166 167
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

168
table: net_type TABLE SYM table_sorted {
169
   struct rtable_config *cf;
170 171
   cf = rt_new_table($3, $1);
   cf->sorted = $4;
172 173 174
   }
 ;

175

176 177
/* Definition of protocols */

178
CF_ADDTO(conf, proto { proto_postconfig(); })
179

180 181 182
proto_start:
   PROTOCOL { $$ = SYM_PROTO; }
 | TEMPLATE { $$ = SYM_TEMPLATE; }
183
 ;
184 185 186

proto_name:
   /* EMPTY */ {
187
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
188
     s->class = this_proto->class;
189 190 191 192
     s->def = this_proto;
     this_proto->name = s->name;
     }
 | SYM {
193
     cf_define_symbol($1, this_proto->class, this_proto);
194 195
     this_proto->name = $1->name;
   }
196 197
 | FROM SYM {
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
198 199
     s->class = this_proto->class;
     s->def = this_proto;
200
     this_proto->name = s->name;
201

202 203 204
     if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected");
     proto_copy_config(this_proto, $2->def);
   }
205 206 207 208
 | SYM FROM SYM {
     cf_define_symbol($1, this_proto->class, this_proto);
     this_proto->name = $1->name;

209
     if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
210 211
     proto_copy_config(this_proto, $3->def);
   }
212 213 214 215
 ;

proto_item:
   /* EMPTY */
216
 | DISABLED bool { this_proto->disabled = $2; }
217
 | DEBUG debug_mask { this_proto->debug = $2; }
218
 | MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
219
 | ROUTER ID idval { this_proto->router_id = $3; }
220
 | DESCRIPTION text { this_proto->dsc = $2; }
221 222
 ;

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

channel_start: net_type
{
  $$ = this_channel = channel_config_new(NULL, $1, this_proto);
};

channel_item:
   TABLE rtable {
     if (this_channel->net_type && ($2->addr_type != this_channel->net_type))
       cf_error("Incompatible table type");
     this_channel->table = $2;
   }
 | IMPORT imexport { this_channel->in_filter = $2; }
 | EXPORT imexport { this_channel->out_filter = $2; }
 | RECEIVE LIMIT limit_spec { this_channel->rx_limit = $3; }
 | IMPORT LIMIT limit_spec { this_channel->in_limit = $3; }
 | EXPORT LIMIT limit_spec { this_channel->out_limit = $3; }
 | PREFERENCE expr { this_channel->preference = $2; check_u16($2); }
 | IMPORT KEEP FILTERED bool { this_channel->in_keep_filtered = $4; }
 ;

channel_opts:
   /* empty */
 | channel_opts channel_item ';'
 ;

channel_opt_list:
   /* empty */
 | '{' channel_opts '}'
 ;

channel_end:
{
  if (!this_channel->table)
    cf_error("Routing table not specified");

  this_channel = NULL;
};

proto_channel: channel_start channel_opt_list channel_end;


rtable:
   SYM {
     if ($1->class != SYM_TABLE) cf_error("Table expected");
     $$ = $1->def;
   }
 ;

272 273
imexport:
   FILTER filter { $$ = $2; }
274
 | where_filter
275 276
 | ALL { $$ = FILTER_ACCEPT; }
 | NONE { $$ = FILTER_REJECT; }
277 278
 ;

279
limit_action:
280
   /* default */ { $$ = PLA_DISABLE; }
281 282 283 284
 | ACTION WARN { $$ = PLA_WARN; }
 | ACTION BLOCK { $$ = PLA_BLOCK; }
 | ACTION RESTART { $$ = PLA_RESTART; }
 | ACTION DISABLE { $$ = PLA_DISABLE; }
285 286 287
 ;

limit_spec:
288 289
   expr limit_action { $$ = (struct channel_limit){ .limit = $1, $$.action = $2 }; }
 | OFF { $$ = (struct channel_limit){}; }
290 291
 ;

292 293 294 295
CF_ADDTO(conf, debug_default)

debug_default:
   DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
296
 | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
297 298
 ;

299 300
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */

301 302
/* Interface patterns */

303 304 305 306 307 308 309 310 311
iface_patt_node_init:
   /* EMPTY */ {
     struct iface_patt_node *ipn = cfg_allocz(sizeof(struct iface_patt_node));
     add_tail(&this_ipatt->ipn_list, NODE ipn);
     this_ipn = ipn;
   }
 ;

iface_patt_node_body:
312 313
   TEXT { this_ipn->pattern = $1; /* this_ipn->prefix stays zero */ }
 | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2; }
314 315 316 317 318 319 320 321
 ;

iface_negate:
       { this_ipn->positive = 1; }
 | '-' { this_ipn->positive = 0; }
 ;

iface_patt_node:
322
   iface_patt_node_init iface_negate iface_patt_node_body
323 324 325 326 327 328
 ;


iface_patt_list:
   iface_patt_node
 | iface_patt_list ',' iface_patt_node
329 330
 ;

331 332 333
/* For name/mask-only iface patterns */
iface_patt_list_nopx: iface_patt_list { iface_patt_check(); }

334 335 336 337 338 339 340 341 342 343 344
iface_patt_init: {
   /* Generic this_ipatt init */
   this_ipatt = cfg_allocz(sizeof(struct iface_patt));
   init_list(&this_ipatt->ipn_list);
 }
 ;

iface_patt:
   iface_patt_init iface_patt_list
 ;

345 346 347 348
tos:
   CLASS expr { $$ = $2 & 0xfc;        if (($2 < 0) || ($2 > 255)) cf_error("TX class must be in range 0-255"); }
 | DSCP expr  { $$ = ($2 & 0x3f) << 2; if (($2 < 0) || ($2 > 63))  cf_error("TX DSCP must be in range 0-63"); }
 ;
349

350
/* Direct device route protocol */
351 352 353

CF_ADDTO(proto, dev_proto '}')

354
dev_proto_start: proto_start DIRECT {
355
     this_proto = proto_config_new(&proto_device, $1);
356
     init_list(&DIRECT_CFG->iface_list);
357 358 359 360
   }
 ;

dev_proto:
361
   dev_proto_start proto_name '{'
362
 | dev_proto proto_item ';'
363
 | dev_proto proto_channel ';'
364
 | dev_proto dev_iface_patt ';'
365
 | dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
366 367
 ;

368
dev_iface_init:
369
   /* EMPTY */ {
370
     this_ipatt = cfg_allocz(sizeof(struct iface_patt));
371
     add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
372
     init_list(&this_ipatt->ipn_list);
373 374 375
   }
 ;

376 377
dev_iface_patt:
   INTERFACE dev_iface_init iface_patt_list
378 379
 ;

380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
/* Debug flags */

debug_mask:
   ALL { $$ = ~0; }
 | OFF { $$ = 0; }
 | '{' debug_list '}' { $$ = $2; }
 ;

debug_list:
   debug_flag
 | debug_list ',' debug_flag { $$ = $1 | $3; }
 ;

debug_flag:
   STATES	{ $$ = D_STATES; }
 | ROUTES	{ $$ = D_ROUTES; }
 | FILTERS	{ $$ = D_FILTERS; }
397
 | INTERFACES	{ $$ = D_IFACES; }
398 399 400 401
 | EVENTS	{ $$ = D_EVENTS; }
 | PACKETS	{ $$ = D_PACKETS; }
 ;

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
/* MRTDump flags */

mrtdump_mask:
   ALL { $$ = ~0; }
 | OFF { $$ = 0; }
 | '{' mrtdump_list '}' { $$ = $2; }
 ;

mrtdump_list:
   mrtdump_flag
 | mrtdump_list ',' mrtdump_flag { $$ = $1 | $3; }
 ;

mrtdump_flag:
   STATES	{ $$ = MD_STATES; }
 | MESSAGES	{ $$ = MD_MESSAGES; }
 ;

420 421
/* Password lists */

422 423 424 425 426
password_list:
   PASSWORDS '{' password_items '}'
 | password_item
;

427
password_items:
428 429 430 431 432 433 434 435 436 437
    /* empty */
  | password_item ';' password_items
;

password_item:
    password_item_begin '{' password_item_params '}'
  | password_item_begin
;

password_item_begin:
438
   PASSWORD text {
439 440 441 442 443
     if (!this_p_list) {
     	this_p_list = cfg_alloc(sizeof(list));
     	init_list(this_p_list);
        password_id = 1;
     }
444 445
     this_p_item = cfg_alloc(sizeof (struct password_item));
     this_p_item->password = $2;
446
     this_p_item->length = strlen($2);
447 448 449 450
     this_p_item->genfrom = 0;
     this_p_item->gento = TIME_INFINITY;
     this_p_item->accfrom = 0;
     this_p_item->accto = TIME_INFINITY;
451
     this_p_item->id = password_id++;
452
     this_p_item->alg = ALG_UNDEFINED;
453
     add_tail(this_p_list, &this_p_item->n);
454
   }
455
;
456

457
password_item_params:
458
   /* empty */ { }
459 460 461 462
 | GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; }
 | GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; }
 | ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; }
 | ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; }
463 464
 | FROM datetime ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
 | TO datetime ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
465
 | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
466
 | ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
467 468
 ;

469 470 471 472 473 474 475 476 477 478 479 480
password_algorithm:
   KEYED MD5	{ $$ = ALG_MD5; }
 | KEYED SHA1	{ $$ = ALG_SHA1; }
 | KEYED SHA256	{ $$ = ALG_SHA256; }
 | KEYED SHA384	{ $$ = ALG_SHA384; }
 | KEYED SHA512	{ $$ = ALG_SHA512; }
 | HMAC MD5	{ $$ = ALG_HMAC_MD5; }
 | HMAC SHA1	{ $$ = ALG_HMAC_SHA1; }
 | HMAC SHA256	{ $$ = ALG_HMAC_SHA256; }
 | HMAC SHA384	{ $$ = ALG_HMAC_SHA384; }
 | HMAC SHA512	{ $$ = ALG_HMAC_SHA512; }
 ;
481

482
/* Core commands */
483
CF_CLI_HELP(SHOW, ..., [[Show status information]])
484

485
CF_CLI(SHOW STATUS,,, [[Show router status]])
486
{ cmd_show_status(); } ;
487

488 489 490
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
{ cmd_show_memory(); } ;

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

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

497 498 499 500 501
optsym:
   SYM
 | /* empty */ { $$ = NULL; }
 ;

502 503 504 505 506 507
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
{ if_show(); } ;

CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
{ if_show_summary(); } ;

508
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
509
CF_CLI(SHOW ROUTE, r_args, [[[<prefix>|for <prefix>|for <ip>] [table <t>] [filter <f>|where <cond>] [all] [primary] [filtered] [(export|preexport|noexport) <p>] [protocol <p>] [stats|count]]], [[Show routing table]])
510 511 512 513 514
{ rt_show($3); } ;

r_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct rt_show_data));
515
     init_list(&($$->table));
516 517
     $$->filter = FILTER_ACCEPT;
   }
518
 | r_args net_any {
519
     $$ = $1;
520 521
     if ($$->addr) cf_error("Only one prefix expected");
     $$->addr = $2;
522
   }
523
 | r_args FOR net_or_ipa {
524
     $$ = $1;
525
     if ($$->addr) cf_error("Only one prefix expected");
526
     $$->show_for = 1;
527 528
     $$->addr = cfg_alloc($3.length);
     net_copy($$->addr, &($3));
529
   }
530 531 532
 | r_args TABLE SYM {
     $$ = $1;
     if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
533 534 535 536 537 538 539 540 541
     rt_show_add_table($$, ((struct rtable_config *)$3->def)->table);
     $$->tables_defined_by = RSD_TDB_DIRECT;
   }
 | r_args TABLE ALL {
     struct rtable_config *t;
     $$ = $1;
     WALK_LIST(t, config->tables)
       rt_show_add_table($$, t->table);
     $$->tables_defined_by = RSD_TDB_ALL;
542 543 544
   }
 | r_args FILTER filter {
     $$ = $1;
545
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
546 547
     $$->filter = $3;
   }
548 549 550 551 552
 | r_args where_filter {
     $$ = $1;
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
     $$->filter = $2;
   }
553 554 555 556
 | r_args ALL {
     $$ = $1;
     $$->verbose = 1;
   }
557 558 559 560
 | r_args PRIMARY {
     $$ = $1;
     $$->primary_only = 1;
   }
561
 | r_args FILTERED {
562
     $$ = $1;
563
     $$->filtered = 1;
564
   }
565
 | r_args export_mode SYM {
566 567
     struct proto_config *c = (struct proto_config *) $3->def;
     $$ = $1;
568
     if ($$->export_mode) cf_error("Protocol specified twice");
569
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
570 571
     $$->export_mode = $2;
     $$->export_protocol = c->proto;
572
     $$->running_on_config = c->proto->cf->global;
573
     $$->tables_defined_by = RSD_TDB_INDIRECT;
574
   }
575 576 577 578 579 580 581
 | r_args PROTOCOL SYM {
     struct proto_config *c = (struct proto_config *) $3->def;
     $$ = $1;
     if ($$->show_protocol) cf_error("Protocol specified twice");
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
     $$->show_protocol = c->proto;
     $$->running_on_config = c->proto->cf->global;
582
     $$->tables_defined_by = RSD_TDB_INDIRECT;
583
   }
584 585 586 587
 | r_args STATS {
     $$ = $1;
     $$->stats = 1;
   }
588 589 590 591
 | r_args COUNT {
     $$ = $1;
     $$->stats = 2;
   }
592 593 594 595 596 597 598 599 600 601
 | r_args STATS BY TABLE {
     $$ = $1;
     $$->stats = 1;
     $$->stats_by_table = 1;
   }
 | r_args COUNT BY TABLE {
     $$ = $1;
     $$->stats = 2;
     $$->stats_by_table = 1;
   }
602 603
 ;

604 605 606 607
export_mode:
   PREEXPORT	{ $$ = RSEM_PREEXPORT; }
 | EXPORT	{ $$ = RSEM_EXPORT; }
 | NOEXPORT	{ $$ = RSEM_NOEXPORT; }
608 609
 ;

610

611
CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]])
612
CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|<symbol>], [[Show all known symbolic names]])
613 614
{ cmd_show_symbols($3); } ;

615 616 617 618 619 620 621 622 623 624 625 626
sym_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct sym_show_data));
   }
 | sym_args TABLE { $$ = $1; $$->type = SYM_TABLE; }
 | sym_args FUNCTION { $$ = $1; $$->type = SYM_FUNCTION; }
 | sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
 | sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
 | sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
 | sym_args SYM { $$ = $1; $$->sym = $2; }
 ;

627

628 629
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
630
{ rdump(&root_pool); cli_msg(0, ""); } ;
631
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
632
{ sk_dump_all(); cli_msg(0, ""); } ;
633 634
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
{ io_log_dump(); cli_msg(0, ""); } ;
635
CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
636
{ if_dump_all(); cli_msg(0, ""); } ;
637
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
638
{ neigh_dump_all(); cli_msg(0, ""); } ;
639
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
640
{ rta_dump_all(); cli_msg(0, ""); } ;
641
CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
642
{ rt_dump_all(); cli_msg(0, ""); } ;
643
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
644 645
{ protos_dump_all(); cli_msg(0, ""); } ;

646 647 648 649
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
{ cmd_eval($2); } ;

CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
650
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [<buffer-size>], [[Control echoing of log messages]]) {
651 652 653 654 655 656 657
  cli_set_log_echo(this_cli, $2, $3);
  cli_msg(0, "");
} ;

echo_mask:
   ALL { $$ = ~0; }
 | OFF { $$ = 0; }
658
 | '{' log_mask_list '}' { $$ = $2; }
659 660 661 662 663 664 665 666 667
 ;

echo_size:
   /* empty */ { $$ = 4096; }
 | NUM {
     if ($1 < 256 || $1 > 65536) cf_error("Invalid log buffer size");
     $$ = $1;
   }
 ;
668

669
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
670
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
671
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
672
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
673
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
674
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
675
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
676
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
677
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
678
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
679
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
680
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
681

682
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
683
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|routes|filters|interfaces|events|packets [, ...] }), [[Control protocol debugging via BIRD logs]])
684
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
685 686

CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
687
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|messages [, ...] }), [[Control protocol debugging via MRTdump format]])
688 689 690 691
{ 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"); } ;
692

693
proto_patt:
694 695 696
   SYM  { $$.ptr = $1; $$.patt = 0; }
 | ALL  { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
697 698
 ;

699 700 701 702 703 704
proto_patt2:
   SYM  { $$.ptr = $1; $$.patt = 0; }
 |      { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
 ;

705 706 707
CF_ADDTO(dynamic_attr, IGP_METRIC
	{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); })

708

709 710 711
CF_CODE

CF_END