config.Y 19.8 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,
66
	RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL)
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
#endif
     else
114
       cf_error("Number or IPv4 address constant expected");
115
   }
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
 | dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
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]])
Martin Mareš's avatar
Martin Mareš committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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(); } ;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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;
   }
Martin Mareš's avatar
Martin Mareš committed
475
 | r_args prefix {
476
477
     $$ = $1;
     if ($$->pxlen != 256) cf_error("Only one prefix expected");
Martin Mareš's avatar
Martin Mareš committed
478
479
     $$->prefix = $2.addr;
     $$->pxlen = $2.len;
480
   }
481
482
483
484
485
486
487
 | 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;
   }
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

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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; }
 ;


Ondřej Zajíček's avatar
Ondřej Zajíček committed
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;
   }
 ;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
681
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
682
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
683
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
684
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
685
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
686
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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)]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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)]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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]])
Ondřej Zajíček's avatar
Ondřej Zajíček committed
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; }
 ;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
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