config.Y 20.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
#include "lib/mac.h"
17

18 19 20 21
CF_DEFINES

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

28 29 30 31 32 33 34 35 36 37 38
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");
}


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

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

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

55 56
CF_DECLS

57
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
58
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, TABLE, STATES, ROUTES, FILTERS)
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(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
62
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
63
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
64
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
65
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
66

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

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

CF_GRAMMAR

88 89
/* Setting of router ID */

90
CF_ADDTO(conf, rtrid)
91

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

idval:
98
   NUM { $$ = $1; }
99
 | '(' term ')' { $$ = f_eval_int($2); }
100 101 102 103 104
 | RTRID
 | IPA {
#ifndef IPV6
     $$ = ipa_to_u32($1);
#else
105
     cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
106 107
#endif
   }
108 109 110 111 112
 | 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))
113
       $$ = ipa_to_u32(SYM_VAL($1).px.ip);
114 115
#endif
     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 144
/* Creation of routing tables */

145 146 147 148 149
tab_sorted:
          { $$ = 0; }
 | SORTED { $$ = 1; }
 ;

150 151
CF_ADDTO(conf, newtab)

152 153 154 155
newtab: TABLE SYM tab_sorted {
   struct rtable_config *cf;
   cf = rt_new_table($2);
   cf->sorted = $3;
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; }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
230
 | VRF TEXT { this_proto->vrf = if_get_by_name($2); }
231
 | TABLE rtable { this_proto->table = $2; }
232
 | ROUTER ID idval { this_proto->router_id = $3; }
233
 | DESCRIPTION text { this_proto->dsc = $2; }
234 235 236 237
 ;

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

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

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

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

268 269 270 271
CF_ADDTO(conf, debug_default)

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

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

277 278
/* Interface patterns */

279 280 281 282 283 284 285 286 287 288
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; }
289 290
 | 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; }
291 292 293 294 295 296 297 298
 ;

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

iface_patt_node:
299
   iface_patt_node_init iface_negate iface_patt_node_body
300 301 302 303 304 305
 ;


iface_patt_list:
   iface_patt_node
 | iface_patt_list ',' iface_patt_node
306 307
 ;

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

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

322 323 324 325
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"); }
 ;
326

327
/* Direct device route protocol */
328 329 330

CF_ADDTO(proto, dev_proto '}')

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

dev_proto:
338
   dev_proto_start proto_name '{'
339
 | dev_proto proto_item ';'
340
 | dev_proto dev_iface_patt ';'
341
 | dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
342 343
 ;

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

352 353
dev_iface_patt:
   INTERFACE dev_iface_init iface_patt_list
354 355
 ;

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

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

396 397
/* Password lists */

398 399 400 401 402
password_list:
   PASSWORDS '{' password_items '}'
 | password_item
;

403
password_items:
404 405 406 407 408 409 410 411 412 413
    /* empty */
  | password_item ';' password_items
;

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

password_item_begin:
414
   PASSWORD text {
415 416 417 418 419
     if (!this_p_list) {
     	this_p_list = cfg_alloc(sizeof(list));
     	init_list(this_p_list);
        password_id = 1;
     }
420 421
     this_p_item = cfg_alloc(sizeof (struct password_item));
     this_p_item->password = $2;
422
     this_p_item->length = strlen($2);
423 424 425 426
     this_p_item->genfrom = 0;
     this_p_item->gento = TIME_INFINITY;
     this_p_item->accfrom = 0;
     this_p_item->accto = TIME_INFINITY;
427
     this_p_item->id = password_id++;
428
     this_p_item->alg = ALG_UNDEFINED;
429
     add_tail(this_p_list, &this_p_item->n);
430
   }
431
;
432

433
password_item_params:
434
   /* empty */ { }
435 436 437 438
 | 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; }
439 440
 | 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; }
441
 | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
442
 | ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
443 444
 ;

445 446 447 448 449 450 451 452 453 454 455 456
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; }
 ;
457

458
/* Core commands */
459
CF_CLI_HELP(SHOW, ..., [[Show status information]])
460

461
CF_CLI(SHOW STATUS,,, [[Show router status]])
462
{ cmd_show_status(); } ;
463

464 465 466
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
{ cmd_show_memory(); } ;

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

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

473 474 475 476 477
optsym:
   SYM
 | /* empty */ { $$ = NULL; }
 ;

478 479 480 481 482 483
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
{ if_show(); } ;

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

484
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
485
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]])
486 487 488 489 490 491 492 493
{ rt_show($3); } ;

r_args:
   /* empty */ {
     $$ = cfg_allocz(sizeof(struct rt_show_data));
     $$->pxlen = 256;
     $$->filter = FILTER_ACCEPT;
   }
494
 | r_args prefix {
495 496
     $$ = $1;
     if ($$->pxlen != 256) cf_error("Only one prefix expected");
497 498
     $$->prefix = $2.addr;
     $$->pxlen = $2.len;
499
   }
500 501 502 503 504 505 506
 | 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;
   }
507 508 509 510 511 512 513
 | 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;
514
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
515 516
     $$->filter = $3;
   }
517 518 519 520 521
 | r_args where_filter {
     $$ = $1;
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
     $$->filter = $2;
   }
522 523 524 525
 | r_args ALL {
     $$ = $1;
     $$->verbose = 1;
   }
526 527 528 529
 | r_args PRIMARY {
     $$ = $1;
     $$->primary_only = 1;
   }
530
 | r_args FILTERED {
531
     $$ = $1;
532
     $$->filtered = 1;
533
   }
534
 | r_args export_mode SYM {
535 536
     struct proto_config *c = (struct proto_config *) $3->def;
     $$ = $1;
537
     if ($$->export_mode) cf_error("Protocol specified twice");
538
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
539 540
     $$->export_mode = $2;
     $$->export_protocol = c->proto;
541 542
     $$->running_on_config = c->proto->cf->global;
   }
543 544 545 546 547 548 549
 | 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;
550
   }
551 552 553 554
 | r_args STATS {
     $$ = $1;
     $$->stats = 1;
   }
555 556 557 558
 | r_args COUNT {
     $$ = $1;
     $$->stats = 2;
   }
559 560
 ;

561 562 563 564
export_mode:
   PREEXPORT	{ $$ = RSEM_PREEXPORT; }
 | EXPORT	{ $$ = RSEM_EXPORT; }
 | NOEXPORT	{ $$ = RSEM_NOEXPORT; }
565 566
 ;

567

568 569
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]])
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
{ 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; }
 ;


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

609 610 611 612 613 614 615 616 617
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; }
618
 | sym_args ROA { $$ = $1; $$->type = SYM_ROA; }
619 620 621
 | sym_args SYM { $$ = $1; $$->sym = $2; }
 ;

622 623

roa_table_arg:
624
   /* empty */ {
625 626 627 628 629 630 631 632 633 634 635
     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;
   }
 ;

636
CF_CLI_HELP(ADD, roa ..., [[Add ROA record]])
637
CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]])
638 639 640 641
{
  if (! cli_access_restricted())
    { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
642

643
CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]])
644
CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]])
645 646 647 648
{
  if (! cli_access_restricted())
    { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
649

650
CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]])
651
CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]])
652 653 654 655
{
  if (! cli_access_restricted())
    { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
};
656 657


658 659
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
660
{ rdump(&root_pool); cli_msg(0, ""); } ;
661
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
662
{ sk_dump_all(); cli_msg(0, ""); } ;
663 664
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
{ io_log_dump(); cli_msg(0, ""); } ;
665
CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
666
{ if_dump_all(); cli_msg(0, ""); } ;
667
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
668
{ neigh_dump_all(); cli_msg(0, ""); } ;
669
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
670
{ rta_dump_all(); cli_msg(0, ""); } ;
671
CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
672
{ rt_dump_all(); cli_msg(0, ""); } ;
673
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
674 675
{ protos_dump_all(); cli_msg(0, ""); } ;

676 677 678 679
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
{ cmd_eval($2); } ;

CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
680
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [<buffer-size>], [[Control echoing of log messages]]) {
681 682 683 684 685 686 687
  cli_set_log_echo(this_cli, $2, $3);
  cli_msg(0, "");
} ;

echo_mask:
   ALL { $$ = ~0; }
 | OFF { $$ = 0; }
688
 | '{' log_mask_list '}' { $$ = $2; }
689 690 691 692 693 694 695 696 697
 ;

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

699
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
700
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
701
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
702
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
703
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
704
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
705
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
706
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
707
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
708
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
709
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
710
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
711

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

CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
717
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|messages [, ...] }), [[Control protocol debugging via MRTdump format]])
718 719 720 721
{ 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"); } ;
722

723
proto_patt:
724 725 726
   SYM  { $$.ptr = $1; $$.patt = 0; }
 | ALL  { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
727 728
 ;

729 730 731 732 733 734
proto_patt2:
   SYM  { $$.ptr = $1; $$.patt = 0; }
 |      { $$.ptr = NULL; $$.patt = 1; }
 | TEXT { $$.ptr = $1; $$.patt = 1; }
 ;

735 736 737
CF_ADDTO(dynamic_attr, IGP_METRIC
	{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); })

738

739 740 741
CF_CODE

CF_END