Statistics
| Branch: | Revision:

iof-bird-daemon / nest / config.Y @ 5e173e9f

History | View | Annotate | Download (17.1 KB)

1
/*
2
 *	BIRD -- Core Configuration
3
 *
4
 *	(c) 1998--2000 Martin Mares <mj@ucw.cz>
5
 *      (c) 2004       Ondrej Filip <feela@network.cz>
6
 *
7
 *	Can be freely distributed and used under the terms of the GNU GPL.
8
 */
9

    
10
CF_HDR
11

    
12
#include "nest/rt-dev.h"
13
#include "nest/password.h"
14
#include "nest/cmds.h"
15
#include "lib/lists.h"
16

    
17
CF_DEFINES
18

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

    
27
static void
28
iface_patt_check(void)
29
{
30
  struct iface_patt_node *pn;
31

    
32
  WALK_LIST(pn, this_ipatt->ipn_list)
33
    if (!pn->pattern || pn->prefix.pxlen) /* XXXX */
34
      cf_error("Interface name/mask expected, not IP prefix");
35
}
36

    
37

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

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

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

    
54
CF_DECLS
55

    
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,
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
%type <sd> sym_args
79
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode limit_action table_type table_sorted tos
80
%type <ps> proto_patt proto_patt2
81
%type <g> limit_spec
82

    
83
CF_GRAMMAR
84

    
85
/* Setting of router ID */
86

    
87
CF_ADDTO(conf, rtrid)
88

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

    
94
idval:
95
   NUM { $$ = $1; }
96
 | '(' term ')' { $$ = f_eval_int($2); }
97
 | IP4 { $$ = ip4_to_u32($1); }
98
 | SYM {
99
     if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
100
       $$ = SYM_VAL($1).i;
101
     else if (($1->class == (SYM_CONSTANT | T_IP)) && ipa_is_ip4(SYM_VAL($1).ip))
102
       $$ = ipa_to_u32(SYM_VAL($1).ip);
103
     else
104
       cf_error("Number of IPv4 address constant expected");
105
   }
106
 ;
107

    
108

    
109
CF_ADDTO(conf, listen)
110

    
111
listen: LISTEN BGP listen_opts ';' ;
112

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

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

    
125

    
126
CF_ADDTO(conf, gr_opts)
127

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

    
130

    
131
/* Creation of routing tables */
132

    
133
CF_ADDTO(conf, table)
134

    
135
table_type:
136
   /* empty */ { $$ = NET_IP4; }
137
 | IPV4 { $$ = NET_IP4; }
138
 | IPVX { $$ = NET_IP6; } /* XXXX */
139
 | VPN4 { $$ = NET_VPN4; }
140
 | VPN6 { $$ = NET_VPN6; }
141
 ;
142

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

    
148
table: table_type TABLE SYM table_sorted {
149
   struct rtable_config *cf;
150
   cf = rt_new_table($3, $1);
151
   cf->sorted = $4;
152
   }
153
 ;
154

    
155
/* Definition of protocols */
156

    
157
CF_ADDTO(conf, proto)
158

    
159
proto_start:
160
   PROTOCOL { $$ = SYM_PROTO; }
161
 | TEMPLATE { $$ = SYM_TEMPLATE; }
162
 ;
163

    
164
proto_name:
165
   /* EMPTY */ {
166
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
167
     s->class = this_proto->class;
168
     s->def = this_proto;
169
     this_proto->name = s->name;
170
     }
171
 | SYM {
172
     cf_define_symbol($1, this_proto->class, this_proto);
173
     this_proto->name = $1->name;
174
   }
175
 | FROM SYM {
176
     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
177
     s->class = this_proto->class;
178
     s->def = this_proto;
179
     this_proto->name = s->name;
180

    
181
     if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected");
182
     proto_copy_config(this_proto, $2->def);
183
   }
184
 | SYM FROM SYM {
185
     cf_define_symbol($1, this_proto->class, this_proto);
186
     this_proto->name = $1->name;
187

    
188
     if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
189
     proto_copy_config(this_proto, $3->def);
190
   }
191
 ;
192

    
193
proto_item:
194
   /* EMPTY */
195
 | PREFERENCE expr {
196
     if ($2 < 0 || $2 > 0xFFFF) cf_error("Invalid preference");
197
     this_proto->preference = $2;
198
   }
199
 | DISABLED bool { this_proto->disabled = $2; }
200
 | DEBUG debug_mask { this_proto->debug = $2; }
201
 | MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
202
 | IMPORT imexport { this_proto->in_filter = $2; }
203
 | EXPORT imexport { this_proto->out_filter = $2; }
204
 | RECEIVE LIMIT limit_spec { this_proto->rx_limit = $3; }
205
 | IMPORT LIMIT limit_spec { this_proto->in_limit = $3; }
206
 | EXPORT LIMIT limit_spec { this_proto->out_limit = $3; }
207
 | IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
208
 | TABLE rtable { this_proto->table = $2; }
209
 | ROUTER ID idval { this_proto->router_id = $3; }
210
 | DESCRIPTION text { this_proto->dsc = $2; }
211
 ;
212

    
213
imexport:
214
   FILTER filter { $$ = $2; }
215
 | where_filter
216
 | ALL { $$ = FILTER_ACCEPT; }
217
 | NONE { $$ = FILTER_REJECT; }
218
 ;
219

    
220
limit_action:
221
   /* default */ { $$ = PLA_DISABLE; }
222
 | ACTION WARN { $$ = PLA_WARN; }
223
 | ACTION BLOCK { $$ = PLA_BLOCK; }
224
 | ACTION RESTART { $$ = PLA_RESTART; }
225
 | ACTION DISABLE { $$ = PLA_DISABLE; }
226
 ;
227

    
228
limit_spec:
229
   expr limit_action {
230
     struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
231
     l->limit = $1;
232
     l->action = $2;
233
     $$ = l;
234
   }
235
 | OFF { $$ = NULL; }
236
 ;
237

    
238
rtable:
239
   SYM {
240
     if ($1->class != SYM_TABLE) cf_error("Table name expected");
241
     $$ = $1->def;
242
   }
243
 ;
244

    
245
CF_ADDTO(conf, debug_default)
246

    
247
debug_default:
248
   DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
249
 | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
250
 ;
251

    
252
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
253

    
254
/* Interface patterns */
255

    
256
iface_patt_node_init:
257
   /* EMPTY */ {
258
     struct iface_patt_node *ipn = cfg_allocz(sizeof(struct iface_patt_node));
259
     add_tail(&this_ipatt->ipn_list, NODE ipn);
260
     this_ipn = ipn;
261
   }
262
 ;
263

    
264
iface_patt_node_body:
265
   TEXT { this_ipn->pattern = $1; net_fill_ip6(&this_ipn->prefix, IP6_NONE, 0); /* XXXX */ }
266
 | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.n; }
267
 ;
268

    
269
iface_negate:
270
       { this_ipn->positive = 1; }
271
 | '-' { this_ipn->positive = 0; }
272
 ;
273

    
274
iface_patt_node:
275
   iface_patt_node_init iface_negate iface_patt_node_body 
276
 ;
277

    
278

    
279
iface_patt_list:
280
   iface_patt_node
281
 | iface_patt_list ',' iface_patt_node
282
 ;
283

    
284
/* For name/mask-only iface patterns */
285
iface_patt_list_nopx: iface_patt_list { iface_patt_check(); }
286

    
287
iface_patt_init: {
288
   /* Generic this_ipatt init */
289
   this_ipatt = cfg_allocz(sizeof(struct iface_patt));
290
   init_list(&this_ipatt->ipn_list);
291
 }
292
 ;
293

    
294
iface_patt:
295
   iface_patt_init iface_patt_list
296
 ;
297

    
298
tos:
299
   CLASS expr { $$ = $2 & 0xfc;        if (($2 < 0) || ($2 > 255)) cf_error("TX class must be in range 0-255"); }
300
 | DSCP expr  { $$ = ($2 & 0x3f) << 2; if (($2 < 0) || ($2 > 63))  cf_error("TX DSCP must be in range 0-63"); }
301
 ;
302

    
303
/* Direct device route protocol */
304

    
305
CF_ADDTO(proto, dev_proto '}')
306

    
307
dev_proto_start: proto_start DIRECT {
308
     this_proto = proto_config_new(&proto_device, $1);
309
     init_list(&DIRECT_CFG->iface_list);
310
   }
311
 ;
312

    
313
dev_proto:
314
   dev_proto_start proto_name '{'
315
 | dev_proto proto_item ';'
316
 | dev_proto dev_iface_patt ';'
317
 ;
318

    
319
dev_iface_init:
320
   /* EMPTY */ {
321
     this_ipatt = cfg_allocz(sizeof(struct iface_patt));
322
     add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
323
     init_list(&this_ipatt->ipn_list);
324
   }
325
 ;
326

    
327
dev_iface_patt:
328
   INTERFACE dev_iface_init iface_patt_list
329
 ;
330

    
331
/* Debug flags */
332

    
333
debug_mask:
334
   ALL { $$ = ~0; }
335
 | OFF { $$ = 0; }
336
 | '{' debug_list '}' { $$ = $2; }
337
 ;
338

    
339
debug_list:
340
   debug_flag
341
 | debug_list ',' debug_flag { $$ = $1 | $3; }
342
 ;
343

    
344
debug_flag:
345
   STATES	{ $$ = D_STATES; }
346
 | ROUTES	{ $$ = D_ROUTES; }
347
 | FILTERS	{ $$ = D_FILTERS; }
348
 | INTERFACES	{ $$ = D_IFACES; }
349
 | EVENTS	{ $$ = D_EVENTS; }
350
 | PACKETS	{ $$ = D_PACKETS; }
351
 ;
352

    
353
/* MRTDump flags */
354

    
355
mrtdump_mask:
356
   ALL { $$ = ~0; }
357
 | OFF { $$ = 0; }
358
 | '{' mrtdump_list '}' { $$ = $2; }
359
 ;
360

    
361
mrtdump_list:
362
   mrtdump_flag
363
 | mrtdump_list ',' mrtdump_flag { $$ = $1 | $3; }
364
 ;
365

    
366
mrtdump_flag:
367
   STATES	{ $$ = MD_STATES; }
368
 | MESSAGES	{ $$ = MD_MESSAGES; }
369
 ;
370

    
371
/* Password lists */
372

    
373
password_list:
374
   PASSWORDS '{' password_items '}'
375
 | password_item
376
;
377

    
378
password_items: 
379
    /* empty */
380
  | password_item ';' password_items
381
;
382

    
383
password_item:
384
    password_item_begin '{' password_item_params '}'
385
  | password_item_begin
386
;
387

    
388
password_item_begin:
389
   PASSWORD text {
390
     if (!this_p_list) {
391
     	this_p_list = cfg_alloc(sizeof(list));
392
     	init_list(this_p_list);
393
        password_id = 1;
394
     }
395
     this_p_item = cfg_alloc(sizeof (struct password_item));
396
     this_p_item->password = $2;
397
     this_p_item->genfrom = 0;
398
     this_p_item->gento = TIME_INFINITY;
399
     this_p_item->accfrom = 0;
400
     this_p_item->accto = TIME_INFINITY;
401
     this_p_item->id = password_id++;
402
     add_tail(this_p_list, &this_p_item->n);
403
   }
404
;
405

    
406
password_item_params:
407
   /* empty */ { } 
408
 | GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; }
409
 | GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; }
410
 | ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; }
411
 | ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; }
412
 | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
413
 ;
414

    
415

    
416

    
417
/* Core commands */
418
CF_CLI_HELP(SHOW, ..., [[Show status information]])
419

    
420
CF_CLI(SHOW STATUS,,, [[Show router status]])
421
{ cmd_show_status(); } ;
422

    
423
CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
424
{ cmd_show_memory(); } ;
425

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

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

    
432
optsym:
433
   SYM
434
 | /* empty */ { $$ = NULL; }
435
 ;
436

    
437
CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
438
{ if_show(); } ;
439

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

    
443
CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
444
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]])
445
{ rt_show($3); } ;
446

    
447
r_args:
448
   /* empty */ {
449
     $$ = cfg_allocz(sizeof(struct rt_show_data));
450
     $$->filter = FILTER_ACCEPT;
451
   }
452
 | r_args net_any {
453
     $$ = $1;
454
     if ($$->prefix) cf_error("Only one prefix expected");
455
     $$->prefix = $2;
456
   }
457
 | r_args FOR net_or_ipa {
458
     $$ = $1;
459
     if ($$->prefix) cf_error("Only one prefix expected");
460
     $$->prefix = &($3.n);
461
     $$->show_for = 1;
462
   }
463
 | r_args TABLE SYM {
464
     $$ = $1;
465
     if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
466
     $$->table = ((struct rtable_config *)$3->def)->table;
467
   }
468
 | r_args FILTER filter {
469
     $$ = $1;
470
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
471
     $$->filter = $3;
472
   }
473
 | r_args where_filter {
474
     $$ = $1;
475
     if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
476
     $$->filter = $2;
477
   }
478
 | r_args ALL {
479
     $$ = $1;
480
     $$->verbose = 1;
481
   }
482
 | r_args PRIMARY {
483
     $$ = $1;
484
     $$->primary_only = 1;
485
   }
486
 | r_args FILTERED {
487
     $$ = $1;
488
     $$->filtered = 1;
489
   }
490
 | r_args export_mode SYM {
491
     struct proto_config *c = (struct proto_config *) $3->def;
492
     $$ = $1;
493
     if ($$->export_mode) cf_error("Protocol specified twice");
494
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
495
     $$->export_mode = $2;
496
     $$->export_protocol = c->proto;
497
     $$->running_on_config = c->proto->cf->global;
498
   }
499
 | r_args PROTOCOL SYM {
500
     struct proto_config *c = (struct proto_config *) $3->def;
501
     $$ = $1;
502
     if ($$->show_protocol) cf_error("Protocol specified twice");
503
     if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
504
     $$->show_protocol = c->proto;
505
     $$->running_on_config = c->proto->cf->global;
506
   }
507
 | r_args STATS {
508
     $$ = $1;
509
     $$->stats = 1;
510
   }
511
 | r_args COUNT {
512
     $$ = $1;
513
     $$->stats = 2;
514
   }
515
 ;
516

    
517
export_mode:
518
   PREEXPORT	{ $$ = RSEM_PREEXPORT; }
519
 | EXPORT	{ $$ = RSEM_EXPORT; }
520
 | NOEXPORT	{ $$ = RSEM_NOEXPORT; }
521
 ;
522

    
523

    
524
CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]])
525
CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|<symbol>], [[Show all known symbolic names]])
526
{ cmd_show_symbols($3); } ;
527

    
528
sym_args:
529
   /* empty */ {
530
     $$ = cfg_allocz(sizeof(struct sym_show_data));
531
   }
532
 | sym_args TABLE { $$ = $1; $$->type = SYM_TABLE; }
533
 | sym_args FUNCTION { $$ = $1; $$->type = SYM_FUNCTION; }
534
 | sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
535
 | sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
536
 | sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
537
 | sym_args SYM { $$ = $1; $$->sym = $2; }
538
 ;
539

    
540

    
541
CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
542
CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
543
{ rdump(&root_pool); cli_msg(0, ""); } ;
544
CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
545
{ sk_dump_all(); cli_msg(0, ""); } ;
546
CF_CLI(DUMP EVENTS,,, [[Dump event log]])
547
{ io_log_dump(); cli_msg(0, ""); } ;
548
CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
549
{ if_dump_all(); cli_msg(0, ""); } ;
550
CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
551
{ neigh_dump_all(); cli_msg(0, ""); } ;
552
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
553
{ rta_dump_all(); cli_msg(0, ""); } ;
554
CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
555
{ rt_dump_all(); cli_msg(0, ""); } ;
556
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
557
{ protos_dump_all(); cli_msg(0, ""); } ;
558

    
559
CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
560
{ cmd_eval($2); } ;
561

    
562
CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
563
CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug | trace | info | remote | warning | error | auth }) [<buffer-size>], [[Control echoing of log messages]]) {
564
  cli_set_log_echo(this_cli, $2, $3);
565
  cli_msg(0, "");
566
} ;
567

    
568
echo_mask:
569
   ALL { $$ = ~0; }
570
 | OFF { $$ = 0; }
571
 | '{' log_mask_list '}' { $$ = $2; }
572
 ;
573

    
574
echo_size:
575
   /* empty */ { $$ = 4096; }
576
 | NUM {
577
     if ($1 < 256 || $1 > 65536) cf_error("Invalid log buffer size");
578
     $$ = $1;
579
   }
580
 ;
581

    
582
CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
583
{ proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
584
CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
585
{ proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
586
CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
587
{ proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
588
CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
589
{ proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
590
CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
591
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
592
CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
593
{ proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
594

    
595
CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
596
CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | <pattern> | all) (all | off | { states | routes | filters | interfaces | events | packets }), [[Control protocol debugging via BIRD logs]])
597
{ proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
598

    
599
CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
600
CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | <pattern> | all) (all | off | { states | messages }), [[Control protocol debugging via MRTdump format]])
601
{ proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ;
602

    
603
CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]])
604
{ this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ;
605

    
606
proto_patt:
607
   SYM  { $$.ptr = $1; $$.patt = 0; }
608
 | ALL  { $$.ptr = NULL; $$.patt = 1; }
609
 | TEXT { $$.ptr = $1; $$.patt = 1; }
610
 ;
611

    
612
proto_patt2:
613
   SYM  { $$.ptr = $1; $$.patt = 0; }
614
 |      { $$.ptr = NULL; $$.patt = 1; }
615
 | TEXT { $$.ptr = $1; $$.patt = 1; }
616
 ;
617

    
618
CF_ADDTO(dynamic_attr, IGP_METRIC
619
	{ $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); })
620

    
621

    
622
CF_CODE
623

    
624
CF_END