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

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)
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 97 98 99 100 101
   NUM { $$ = $1; }
 | RTRID
 | IPA {
#ifndef IPV6
     $$ = ipa_to_u32($1);
#else
102
     cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
103 104
#endif
   }
105 106
 ;

107

108
CF_ADDTO(conf, listen)
109

110
listen: LISTEN BGP listen_opts ';' ;
111

112
listen_opts:
113
   /* Nothing */
114
 | listen_opts listen_opt
115 116
 ;

117 118 119
listen_opt: 
   ADDRESS ipa { new_config->listen_bgp_addr = $2; }
 | PORT expr { new_config->listen_bgp_port = $2; }
120 121
 | V6ONLY { new_config->listen_bgp_flags = 0; }
 | DUAL { new_config->listen_bgp_flags = 1; }
122 123 124
 ;


125 126 127 128 129
CF_ADDTO(conf, gr_opts)

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


130 131
/* Creation of routing tables */

132 133 134 135 136
tab_sorted:
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

137 138
CF_ADDTO(conf, newtab)

139 140 141 142
newtab: TABLE SYM tab_sorted {
   struct rtable_config *cf;
   cf = rt_new_table($2);
   cf->sorted = $3;
143 144 145
   }
 ;

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
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 '}'
 ;

164 165 166 167
/* Definition of protocols */

CF_ADDTO(conf, proto)

168 169 170
proto_start:
   PROTOCOL { $$ = SYM_PROTO; }
 | TEMPLATE { $$ = SYM_TEMPLATE; }
171
 ;
172 173 174

proto_name:
   /* EMPTY */ {
175
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
176
     s->class = this_proto->class;
177 178 179 180
     s->def = this_proto;
     this_proto->name = s->name;
     }
 | SYM {
181
     cf_define_symbol($1, this_proto->class, this_proto);
182 183
     this_proto->name = $1->name;
   }
184 185
 | FROM SYM {
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
186 187
     s->class = this_proto->class;
     s->def = this_proto;
188
     this_proto->name = s->name;
189

190 191 192
     if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected");
     proto_copy_config(this_proto, $2->def);
   }
193 194 195 196
 | SYM FROM SYM {
     cf_define_symbol($1, this_proto->class, this_proto);
     this_proto->name = $1->name;

197
     if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
198 199
     proto_copy_config(this_proto, $3->def);
   }
200 201 202 203
 ;

proto_item:
   /* EMPTY */
204
 | PREFERENCE expr {
205
     if ($2 < 0 || $2 > 0xFFFF) cf_error("Invalid preference");
206 207
     this_proto->preference = $2;
   }
208
 | DISABLED bool { this_proto->disabled = $2; }
209
 | DEBUG debug_mask { this_proto->debug = $2; }
210
 | MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
211 212
 | IMPORT imexport { this_proto->in_filter = $2; }
 | EXPORT imexport { this_proto->out_filter = $2; }
213
 | RECEIVE LIMIT limit_spec { this_proto->rx_limit = $3; }
214
 | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
215
 | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
216
 | IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
217
 | TABLE rtable { this_proto->table = $2; }
218
 | ROUTER ID idval { this_proto->router_id = $3; }
219
 | DESCRIPTION text { this_proto->dsc = $2; }
220 221 222 223
 ;

imexport:
   FILTER filter { $$ = $2; }
224
 | where_filter
225 226
 | ALL { $$ = FILTER_ACCEPT; }
 | NONE { $$ = FILTER_REJECT; }
227 228
 ;

229
limit_action:
230
   /* default */ { $$ = PLA_DISABLE; }
231 232 233 234
 | ACTION WARN { $$ = PLA_WARN; }
 | ACTION BLOCK { $$ = PLA_BLOCK; }
 | ACTION RESTART { $$ = PLA_RESTART; }
 | ACTION DISABLE { $$ = PLA_DISABLE; }
235 236 237
 ;

limit_spec:
238
   expr limit_action {
239 240
     struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
     l->limit = $1;
241
     l->action = $2;
242 243
     $$ = l;
   }
244
 | OFF { $$ = NULL; }
245 246
 ;

247 248 249 250 251 252 253
rtable:
   SYM {
     if ($1->class != SYM_TABLE) cf_error("Table name expected");
     $$ = $1->def;
   }
 ;

254 255 256 257
CF_ADDTO(conf, debug_default)

debug_default:
   DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
258
 | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
259 260
 ;

261 262
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */

263 264
/* Interface patterns */

265 266 267 268 269 270 271 272 273 274
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; }
275 276
 | 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; }
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
 ;

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
292 293
 ;

294 295 296
/* For name/mask-only iface patterns */
iface_patt_list_nopx: iface_patt_list { iface_patt_check(); }

297 298 299 300 301 302 303 304 305 306 307
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
 ;

308 309 310 311
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"); }
 ;
312

313
/* Direct device route protocol */
314 315 316

CF_ADDTO(proto, dev_proto '}')

317
dev_proto_start: proto_start DIRECT {
318
     this_proto = proto_config_new(&proto_device, $1);
319
     init_list(&DIRECT_CFG->iface_list);
320 321 322 323
   }
 ;

dev_proto:
324
   dev_proto_start proto_name '{'
325
 | dev_proto proto_item ';'
326
 | dev_proto dev_iface_patt ';'
327 328
 ;

329
dev_iface_init:
330
   /* EMPTY */ {
331
     this_ipatt = cfg_allocz(sizeof(struct iface_patt));
332
     add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
333
     init_list(&this_ipatt->ipn_list);
334 335 336
   }
 ;

337 338
dev_iface_patt:
   INTERFACE dev_iface_init iface_patt_list
339 340
 ;

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
/* 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; }
358
 | INTERFACES	{ $$ = D_IFACES; }
359 360 361 362
 | EVENTS	{ $$ = D_EVENTS; }
 | PACKETS	{ $$ = D_PACKETS; }
 ;

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
/* 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; }
 ;

381 382
/* Password lists */

383 384 385 386 387
password_list:
   PASSWORDS '{' password_items '}'
 | password_item
;

388 389 390 391 392 393 394 395 396 397 398
password_items: 
    /* empty */
  | password_item ';' password_items
;

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

password_item_begin:
399
   PASSWORD text {
400 401 402 403 404
     if (!this_p_list) {
     	this_p_list = cfg_alloc(sizeof(list));
     	init_list(this_p_list);
        password_id = 1;
     }
405 406 407 408 409 410
     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;
411
     this_p_item->id = password_id++;
412
     add_tail(this_p_list, &this_p_item->n);
413
   }
414
;
415

416
password_item_params:
417
   /* empty */ { } 
418 419 420 421
 | 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; }
422
 | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
423 424 425
 ;


426

427
/* Core commands */
428
CF_CLI_HELP(SHOW, ..., [[Show status information]])
429

430
CF_CLI(SHOW STATUS,,, [[Show router status]])
431
{ cmd_show_status(); } ;
432

433 434 435
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
{ cmd_show_memory(); } ;

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

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

442 443 444 445 446
optsym:
   SYM
 | /* empty */ { $$ = NULL; }
 ;

447 448 449 450 451 452
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
{ if_show(); } ;

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

453
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
454
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]])
455 456 457 458 459 460 461 462
{ rt_show($3); } ;

r_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct rt_show_data));
     $$->pxlen = 256;
     $$->filter = FILTER_ACCEPT;
   }
463
 | r_args prefix {
464 465
     $$ = $1;
     if ($$->pxlen != 256) cf_error("Only one prefix expected");
466 467
     $$->prefix = $2.addr;
     $$->pxlen = $2.len;
468
   }
469 470 471 472 473 474 475
 | 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;
   }
476 477 478 479 480 481 482
 | 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;
483
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
484 485
     $$->filter = $3;
   }
486 487 488 489 490
 | r_args where_filter {
     $$ = $1;
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
     $$->filter = $2;
   }
491 492 493 494
 | r_args ALL {
     $$ = $1;
     $$->verbose = 1;
   }
495 496 497 498
 | r_args PRIMARY {
     $$ = $1;
     $$->primary_only = 1;
   }
499
 | r_args FILTERED {
500
     $$ = $1;
501
     $$->filtered = 1;
502
   }
503
 | r_args export_mode SYM {
504 505
     struct proto_config *c = (struct proto_config *) $3->def;
     $$ = $1;
506
     if ($$->export_mode) cf_error("Protocol specified twice");
507
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
508 509
     $$->export_mode = $2;
     $$->export_protocol = c->proto;
510 511
     $$->running_on_config = c->proto->cf->global;
   }
512 513 514 515 516 517 518
 | 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;
519
   }
520 521 522 523
 | r_args STATS {
     $$ = $1;
     $$->stats = 1;
   }
524 525 526 527
 | r_args COUNT {
     $$ = $1;
     $$->stats = 2;
   }
528 529
 ;

530 531 532 533
export_mode:
   PREEXPORT	{ $$ = RSEM_PREEXPORT; }
 | EXPORT	{ $$ = RSEM_EXPORT; }
 | NOEXPORT	{ $$ = RSEM_NOEXPORT; }
534 535
 ;

536

537 538
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]])
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
{ 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; }
 ;


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

578 579 580 581 582 583 584 585 586
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; }
587
 | sym_args ROA { $$ = $1; $$->type = SYM_ROA; }
588 589 590
 | sym_args SYM { $$ = $1; $$->sym = $2; }
 ;

591 592 593 594 595 596 597 598 599 600 601 602 603 604

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;
   }
 ;

605
CF_CLI_HELP(ADD, roa ..., [[Add ROA record]])
606
CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]])
607 608 609 610
{
  if (! cli_access_restricted())
    { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
611

612
CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]])
613
CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]])
614 615 616 617
{
  if (! cli_access_restricted())
    { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
618

619
CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]])
620
CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]])
621 622 623 624
{
  if (! cli_access_restricted())
    { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
625 626


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

645 646 647 648 649
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]]) {
650 651 652 653 654 655 656
  cli_set_log_echo(this_cli, $2, $3);
  cli_msg(0, "");
} ;

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

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

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

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

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]])
687 688 689 690
{ 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"); } ;
691

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

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

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

707

708 709 710
CF_CODE

CF_END