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
static void
iface_patt_check(void)
{
  struct iface_patt_node *pn;

  WALK_LIST(pn, this_ipatt->ipn_list)
33
    if (!pn->pattern || pn->prefix.pxlen) /* XXXX */
34 35 36 37
      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(IPV4, IPVX, VPN4, VPN6)
59
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
60
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
61
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
62
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
63
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
64
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
65

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

73
%type <i32> idval
74
%type <f> imexport
75
%type <r> rtable
76
%type <s> optsym
77
%type <ra> r_args
78 79
%type <ro> roa_args
%type <rot> roa_table_arg
80
%type <sd> sym_args
81
%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 table_type table_sorted tos
82
%type <ps> proto_patt proto_patt2
83
%type <g> limit_spec
84 85 86

CF_GRAMMAR

87 88
/* Setting of router ID */

89
CF_ADDTO(conf, rtrid)
90

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

idval:
97
   NUM { $$ = $1; }
98
 | '(' term ')' { $$ = f_eval_int($2); }
99
 | IP4 { $$ = ip4_to_u32($1); }
100 101 102 103 104
 | 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))
105
       $$ = ipa_to_u32(SYM_VAL($1).px.ip);
106 107 108 109
#endif
     else
       cf_error("Number of IPv4 address constant expected");
   }
110 111
 ;

112

113
CF_ADDTO(conf, listen)
114

115
listen: LISTEN BGP listen_opts ';' ;
116

117
listen_opts:
118
   /* Nothing */
119
 | listen_opts listen_opt
120 121
 ;

122 123 124
listen_opt: 
   ADDRESS ipa { new_config->listen_bgp_addr = $2; }
 | PORT expr { new_config->listen_bgp_port = $2; }
125 126
 | V6ONLY { new_config->listen_bgp_flags = 0; }
 | DUAL { new_config->listen_bgp_flags = 1; }
127 128 129
 ;


130 131 132 133 134
CF_ADDTO(conf, gr_opts)

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


135 136
/* Creation of routing tables */

137 138 139 140 141 142 143 144 145 146 147
CF_ADDTO(conf, table)

table_type:
   /* empty */ { $$ = NET_IP4; }
 | IPV4 { $$ = NET_IP4; }
 | IPVX { $$ = NET_IP6; } /* XXXX */
 | VPN4 { $$ = NET_VPN4; }
 | VPN6 { $$ = NET_VPN6; }
 ;

table_sorted:
148 149 150 151
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

152
table: table_type TABLE SYM table_sorted {
153
   struct rtable_config *cf;
154 155
   cf = rt_new_table($3, $1);
   cf->sorted = $4;
156 157 158
   }
 ;

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
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 '}'
 ;

177 178 179 180
/* Definition of protocols */

CF_ADDTO(conf, proto)

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

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

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

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

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

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

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

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

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

267 268 269 270
CF_ADDTO(conf, debug_default)

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

274 275
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */

276 277
/* Interface patterns */

278 279 280 281 282 283 284 285 286
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:
287 288
   TEXT { this_ipn->pattern = $1; net_fill_ip6(&this_ipn->prefix, IP6_NONE, 0); /* XXXX */ }
 | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.n; }
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
 ;

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
304 305
 ;

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

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

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

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

CF_ADDTO(proto, dev_proto '}')

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

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

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

349 350
dev_iface_patt:
   INTERFACE dev_iface_init iface_patt_list
351 352
 ;

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

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

393 394
/* Password lists */

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

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

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

password_item_begin:
411
   PASSWORD text {
412 413 414 415 416
     if (!this_p_list) {
     	this_p_list = cfg_alloc(sizeof(list));
     	init_list(this_p_list);
        password_id = 1;
     }
417 418 419 420 421 422
     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;
423
     this_p_item->id = password_id++;
424
     add_tail(this_p_list, &this_p_item->n);
425
   }
426
;
427

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


438

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

442
CF_CLI(SHOW STATUS,,, [[Show router status]])
443
{ cmd_show_status(); } ;
444

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

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

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

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

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

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

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

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

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

548

549 550
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]])
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 585
{ 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; }
 ;


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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

719

720 721 722
CF_CODE

CF_END