config.Y 19.7 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

17 18 19 20
CF_DEFINES

static struct proto_config *this_proto;
static struct iface_patt *this_ipatt;
21
static struct iface_patt_node *this_ipn;
22
static struct roa_table_config *this_roa_table;
23 24
static list *this_p_list;
static struct password_item *this_p_item;
25 26
static int password_id;

27 28 29 30 31 32 33 34 35 36 37
static void
iface_patt_check(void)
{
  struct iface_patt_node *pn;

  WALK_LIST(pn, this_ipatt->ipn_list)
    if (!pn->pattern || pn->pxlen)
      cf_error("Interface name/mask expected, not IP prefix");
}


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

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

52
#define DIRECT_CFG ((struct rt_dev_config *) this_proto)
53

54 55
CF_DECLS

56
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
57
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
58
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
59
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
60
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
61
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
62
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
63
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
64

65
CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT,
Ondřej Filip's avatar
Ondřej Filip committed
66
	RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE)
67
CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED)
68
CF_ENUM(T_ENUM_RTC, RTC_, UNICAST, BROADCAST, MULTICAST, ANYCAST)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
69
CF_ENUM(T_ENUM_RTD, RTD_, ROUTER, DEVICE, BLACKHOLE, UNREACHABLE, PROHIBIT, MULTIPATH)
70
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
71

72
%type <i32> idval
73
%type <f> imexport
74
%type <r> rtable
75
%type <s> optsym
76
%type <ra> r_args
77 78
%type <ro> roa_args
%type <rot> roa_table_arg
79
%type <sd> sym_args
80
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos
81
%type <ps> proto_patt proto_patt2
82
%type <g> limit_spec
83 84 85

CF_GRAMMAR

86 87
/* Setting of router ID */

88
CF_ADDTO(conf, rtrid)
89

90 91 92
rtrid: 
   ROUTER ID idval ';' { new_config->router_id = $3; }
 | ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; }
93 94 95
 ;

idval:
96
   NUM { $$ = $1; }
97
 | '(' term ')' { $$ = f_eval_int($2); }
98 99 100 101 102
 | RTRID
 | IPA {
#ifndef IPV6
     $$ = ipa_to_u32($1);
#else
103
     cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
104 105
#endif
   }
106 107 108 109 110
 | SYM {
     if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
       $$ = SYM_VAL($1).i;
#ifndef IPV6
     else if ($1->class == (SYM_CONSTANT | T_IP))
111
       $$ = ipa_to_u32(SYM_VAL($1).px.ip);
112 113 114 115
#endif
     else
       cf_error("Number of IPv4 address constant expected");
   }
116 117
 ;

118

119
CF_ADDTO(conf, listen)
120

121
listen: LISTEN BGP listen_opts ';' ;
122

123
listen_opts:
124
   /* Nothing */
125
 | listen_opts listen_opt
126 127
 ;

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


136 137 138 139 140
CF_ADDTO(conf, gr_opts)

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


141 142
/* Creation of routing tables */

143 144 145 146 147
tab_sorted:
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

148 149
CF_ADDTO(conf, newtab)

150 151 152 153
newtab: TABLE SYM tab_sorted {
   struct rtable_config *cf;
   cf = rt_new_table($2);
   cf->sorted = $3;
154 155 156
   }
 ;

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
CF_ADDTO(conf, roa_table)

roa_table_start: ROA TABLE SYM {
  this_roa_table = roa_new_table_config($3);
};

roa_table_opts:
   /* empty */
 | roa_table_opts ROA prefix MAX NUM AS NUM ';' {
     roa_add_item_config(this_roa_table, $3.addr, $3.len, $5, $7);
   }
 ;

roa_table:
   roa_table_start
 | roa_table_start '{' roa_table_opts '}'
 ;

175 176 177 178
/* Definition of protocols */

CF_ADDTO(conf, proto)

179 180 181
proto_start:
   PROTOCOL { $$ = SYM_PROTO; }
 | TEMPLATE { $$ = SYM_TEMPLATE; }
Martin Mareš's avatar
Martin Mareš committed
182
 ;
183 184 185

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

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

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

proto_item:
   /* EMPTY */
215
 | PREFERENCE expr {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
216
     if ($2 < 0 || $2 > 0xFFFF) cf_error("Invalid preference");
217 218
     this_proto->preference = $2;
   }
Pavel Machek's avatar
Pavel Machek committed
219
 | DISABLED bool { this_proto->disabled = $2; }
220
 | DEBUG debug_mask { this_proto->debug = $2; }
221
 | MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
222 223
 | IMPORT imexport { this_proto->in_filter = $2; }
 | EXPORT imexport { this_proto->out_filter = $2; }
224
 | RECEIVE LIMIT limit_spec { this_proto->rx_limit = $3; }
225
 | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
226
 | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
227
 | IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
228
 | TABLE rtable { this_proto->table = $2; }
229
 | ROUTER ID idval { this_proto->router_id = $3; }
230
 | DESCRIPTION text { this_proto->dsc = $2; }
231 232 233 234
 ;

imexport:
   FILTER filter { $$ = $2; }
235
 | where_filter
236 237
 | ALL { $$ = FILTER_ACCEPT; }
 | NONE { $$ = FILTER_REJECT; }
238 239
 ;

240
limit_action:
241
   /* default */ { $$ = PLA_DISABLE; }
242 243 244 245
 | ACTION WARN { $$ = PLA_WARN; }
 | ACTION BLOCK { $$ = PLA_BLOCK; }
 | ACTION RESTART { $$ = PLA_RESTART; }
 | ACTION DISABLE { $$ = PLA_DISABLE; }
246 247 248
 ;

limit_spec:
249
   expr limit_action {
250 251
     struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
     l->limit = $1;
252
     l->action = $2;
253 254
     $$ = l;
   }
255
 | OFF { $$ = NULL; }
256 257
 ;

258 259 260 261 262 263 264
rtable:
   SYM {
     if ($1->class != SYM_TABLE) cf_error("Table name expected");
     $$ = $1->def;
   }
 ;

265 266 267 268
CF_ADDTO(conf, debug_default)

debug_default:
   DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
269
 | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
270 271
 ;

272 273
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */

274 275
/* Interface patterns */

276 277 278 279 280 281 282 283 284 285
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:
   TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; }
286 287
 | prefix_or_ipa { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; }
 | TEXT prefix_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; }
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
 ;

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

iface_patt_node:
   iface_patt_node_init iface_negate iface_patt_node_body 
 ;


iface_patt_list:
   iface_patt_node
 | iface_patt_list ',' iface_patt_node
303 304
 ;

305 306 307
/* For name/mask-only iface patterns */
iface_patt_list_nopx: iface_patt_list { iface_patt_check(); }

308 309 310 311 312 313 314 315 316 317 318
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
 ;

319 320 321 322
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"); }
 ;
323

324
/* Direct device route protocol */
325 326 327

CF_ADDTO(proto, dev_proto '}')

328
dev_proto_start: proto_start DIRECT {
329
     this_proto = proto_config_new(&proto_device, $1);
330
     init_list(&DIRECT_CFG->iface_list);
331 332 333 334
   }
 ;

dev_proto:
335
   dev_proto_start proto_name '{'
336
 | dev_proto proto_item ';'
337
 | dev_proto dev_iface_patt ';'
338 339
 ;

340
dev_iface_init:
341
   /* EMPTY */ {
342
     this_ipatt = cfg_allocz(sizeof(struct iface_patt));
343
     add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
344
     init_list(&this_ipatt->ipn_list);
345 346 347
   }
 ;

348 349
dev_iface_patt:
   INTERFACE dev_iface_init iface_patt_list
350 351
 ;

352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
/* 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; }
369
 | INTERFACES	{ $$ = D_IFACES; }
370 371 372 373
 | EVENTS	{ $$ = D_EVENTS; }
 | PACKETS	{ $$ = D_PACKETS; }
 ;

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
/* 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; }
 ;

392 393
/* Password lists */

394 395 396 397 398
password_list:
   PASSWORDS '{' password_items '}'
 | password_item
;

399 400 401 402 403 404 405 406 407 408 409
password_items: 
    /* empty */
  | password_item ';' password_items
;

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

password_item_begin:
410
   PASSWORD text {
411 412 413 414 415
     if (!this_p_list) {
     	this_p_list = cfg_alloc(sizeof(list));
     	init_list(this_p_list);
        password_id = 1;
     }
416 417 418 419 420 421
     this_p_item = cfg_alloc(sizeof (struct password_item));
     this_p_item->password = $2;
     this_p_item->genfrom = 0;
     this_p_item->gento = TIME_INFINITY;
     this_p_item->accfrom = 0;
     this_p_item->accto = TIME_INFINITY;
422
     this_p_item->id = password_id++;
423
     add_tail(this_p_list, &this_p_item->n);
424
   }
425
;
426

427
password_item_params:
428
   /* empty */ { } 
429 430 431 432
 | 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; }
433
 | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
434 435 436
 ;


437

438
/* Core commands */
439
CF_CLI_HELP(SHOW, ..., [[Show status information]])
440

441
CF_CLI(SHOW STATUS,,, [[Show router status]])
Martin Mareš's avatar
Martin Mareš committed
442
{ cmd_show_status(); } ;
443

444 445 446
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
{ cmd_show_memory(); } ;

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

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

453 454 455 456 457
optsym:
   SYM
 | /* empty */ { $$ = NULL; }
 ;

458 459 460 461 462 463
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
{ if_show(); } ;

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

464
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
465
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]])
466 467 468 469 470 471 472 473
{ rt_show($3); } ;

r_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct rt_show_data));
     $$->pxlen = 256;
     $$->filter = FILTER_ACCEPT;
   }
Martin Mareš's avatar
Martin Mareš committed
474
 | r_args prefix {
475 476
     $$ = $1;
     if ($$->pxlen != 256) cf_error("Only one prefix expected");
Martin Mareš's avatar
Martin Mareš committed
477 478
     $$->prefix = $2.addr;
     $$->pxlen = $2.len;
479
   }
480 481 482 483 484 485 486
 | r_args FOR prefix_or_ipa {
     $$ = $1;
     if ($$->pxlen != 256) cf_error("Only one prefix expected");
     $$->prefix = $3.addr;
     $$->pxlen = $3.len;
     $$->show_for = 1;
   }
487 488 489 490 491 492 493
 | r_args TABLE SYM {
     $$ = $1;
     if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
     $$->table = ((struct rtable_config *)$3->def)->table;
   }
 | r_args FILTER filter {
     $$ = $1;
494
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
495 496
     $$->filter = $3;
   }
497 498 499 500 501
 | r_args where_filter {
     $$ = $1;
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
     $$->filter = $2;
   }
502 503 504 505
 | r_args ALL {
     $$ = $1;
     $$->verbose = 1;
   }
506 507 508 509
 | r_args PRIMARY {
     $$ = $1;
     $$->primary_only = 1;
   }
510
 | r_args FILTERED {
511
     $$ = $1;
512
     $$->filtered = 1;
513
   }
514
 | r_args export_mode SYM {
515 516
     struct proto_config *c = (struct proto_config *) $3->def;
     $$ = $1;
517
     if ($$->export_mode) cf_error("Protocol specified twice");
518
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
519 520
     $$->export_mode = $2;
     $$->export_protocol = c->proto;
521 522
     $$->running_on_config = c->proto->cf->global;
   }
523 524 525 526 527 528 529
 | 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;
530
   }
531 532 533 534
 | r_args STATS {
     $$ = $1;
     $$->stats = 1;
   }
535 536 537 538
 | r_args COUNT {
     $$ = $1;
     $$->stats = 2;
   }
539 540
 ;

541 542 543 544
export_mode:
   PREEXPORT	{ $$ = RSEM_PREEXPORT; }
 | EXPORT	{ $$ = RSEM_EXPORT; }
 | NOEXPORT	{ $$ = RSEM_NOEXPORT; }
545 546
 ;

547

548 549
CF_CLI_HELP(SHOW ROA, ..., [[Show ROA table]])
CF_CLI(SHOW ROA, roa_args, [<prefix> | in <prefix> | for <prefix>] [as <num>] [table <t>], [[Show ROA table]])
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
{ roa_show($3); } ;

roa_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct roa_show_data));
     $$->mode = ROA_SHOW_ALL;
     $$->table = roa_table_default;
     if (roa_table_default == NULL)
       cf_error("No ROA table defined");
   }
 | roa_args roa_mode prefix {
     $$ = $1;
     if ($$->mode != ROA_SHOW_ALL) cf_error("Only one prefix expected");
     $$->prefix = $3.addr;
     $$->pxlen = $3.len;
     $$->mode = $2;
   }
 | roa_args AS NUM {
     $$ = $1;
     $$->asn = $3;
   }
 | roa_args TABLE SYM {
     $$ = $1;
     if ($3->class != SYM_ROA) cf_error("%s is not a ROA table", $3->name);
     $$->table = ((struct roa_table_config *)$3->def)->table;
   }
 ;

roa_mode:
       { $$ = ROA_SHOW_PX; }
 | IN  { $$ = ROA_SHOW_IN; }
 | FOR { $$ = ROA_SHOW_FOR; }
 ;


585
CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]])
586
CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|roa|<symbol>], [[Show all known symbolic names]])
587 588
{ cmd_show_symbols($3); } ;

589 590 591 592 593 594 595 596 597
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; }
598
 | sym_args ROA { $$ = $1; $$->type = SYM_ROA; }
599 600 601
 | sym_args SYM { $$ = $1; $$->sym = $2; }
 ;

602 603 604 605 606 607 608 609 610 611 612 613 614 615

roa_table_arg:
   /* empty */ { 
     if (roa_table_default == NULL)
       cf_error("No ROA table defined");
     $$ = roa_table_default;
   }
 | TABLE SYM {
     if ($2->class != SYM_ROA)
       cf_error("%s is not a ROA table", $2->name);
     $$ = ((struct roa_table_config *)$2->def)->table;
   }
 ;

616
CF_CLI_HELP(ADD, roa ..., [[Add ROA record]])
617
CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]])
618 619 620 621
{
  if (! cli_access_restricted())
    { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
622

623
CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]])
624
CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]])
625 626 627 628
{
  if (! cli_access_restricted())
    { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
629

630
CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]])
631
CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]])
632 633 634 635
{
  if (! cli_access_restricted())
    { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
636 637


638 639
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
640
{ rdump(&root_pool); cli_msg(0, ""); } ;
641
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
642
{ sk_dump_all(); cli_msg(0, ""); } ;
643 644
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
{ io_log_dump(); cli_msg(0, ""); } ;
645
CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
646
{ if_dump_all(); cli_msg(0, ""); } ;
647
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
648
{ neigh_dump_all(); cli_msg(0, ""); } ;
649
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
650
{ rta_dump_all(); cli_msg(0, ""); } ;
651
CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
652
{ rt_dump_all(); cli_msg(0, ""); } ;
653
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
654 655
{ protos_dump_all(); cli_msg(0, ""); } ;

656 657 658 659 660
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]]) {
661 662 663 664 665 666 667
  cli_set_log_echo(this_cli, $2, $3);
  cli_msg(0, "");
} ;

echo_mask:
   ALL { $$ = ~0; }
 | OFF { $$ = 0; }
668
 | '{' log_mask_list '}' { $$ = $2; }
669 670 671 672 673 674 675 676 677
 ;

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

679
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
680
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
681
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
682
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
683
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
684
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
685
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
686
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
687
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
688
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
689
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
690
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
691

692
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
693
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | interfaces | events | packets }), [[Control protocol debugging via BIRD logs]])
694
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
695 696 697

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]])
698 699 700 701
{ 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"); } ;
702

703
proto_patt:
704 705 706
   SYM  { $$.ptr = $1; $$.patt = 0; }
 | ALL  { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
707 708
 ;

709 710 711 712 713 714
proto_patt2:
   SYM  { $$.ptr = $1; $$.patt = 0; }
 |      { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
 ;

715 716 717
CF_ADDTO(dynamic_attr, IGP_METRIC
	{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); })

718

719 720 721
CF_CODE

CF_END