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: #include "lib/mac.h"
17:
18: CF_DEFINES
19:
20: static struct proto_config *this_proto;
21: static struct iface_patt *this_ipatt;
22: static struct iface_patt_node *this_ipn;
23: static struct roa_table_config *this_roa_table;
24: static list *this_p_list;
25: static struct password_item *this_p_item;
26: static int password_id;
27:
28: static void
29: iface_patt_check(void)
30: {
31: struct iface_patt_node *pn;
32:
33: WALK_LIST(pn, this_ipatt->ipn_list)
34: if (!pn->pattern || pn->pxlen)
35: cf_error("Interface name/mask expected, not IP prefix");
36: }
37:
38:
39: static inline void
40: reset_passwords(void)
41: {
42: this_p_list = NULL;
43: }
44:
45: static inline list *
46: get_passwords(void)
47: {
48: list *rv = this_p_list;
49: this_p_list = NULL;
50: return rv;
51: }
52:
53: #define DIRECT_CFG ((struct rt_dev_config *) this_proto)
54:
55: CF_DECLS
56:
57: CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
58: CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, 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: %type <ro> roa_args
80: %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: CF_GRAMMAR
87:
88: /* Setting of router ID */
89:
90: CF_ADDTO(conf, rtrid)
91:
92: rtrid:
93: ROUTER ID idval ';' { new_config->router_id = $3; }
94: | 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: | RTRID
101: | IPA {
102: #ifndef IPV6
103: $$ = ipa_to_u32($1);
104: #else
105: cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
106: #endif
107: }
108: | SYM {
109: if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
110: $$ = SYM_VAL($1).i;
111: #ifndef IPV6
112: else if ($1->class == (SYM_CONSTANT | T_IP))
113: $$ = ipa_to_u32(SYM_VAL($1).px.ip);
114: #endif
115: 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: ADDRESS ipa { new_config->listen_bgp_addr = $2; }
132: | PORT expr { new_config->listen_bgp_port = $2; }
133: | V6ONLY { new_config->listen_bgp_flags = 0; }
134: | DUAL { new_config->listen_bgp_flags = 1; }
135: ;
136:
137:
138: CF_ADDTO(conf, gr_opts)
139:
140: gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
141:
142:
143: /* Creation of routing tables */
144:
145: tab_sorted:
146: { $$ = 0; }
147: | SORTED { $$ = 1; }
148: ;
149:
150: CF_ADDTO(conf, newtab)
151:
152: newtab: TABLE SYM tab_sorted {
153: struct rtable_config *cf;
154: cf = rt_new_table($2);
155: cf->sorted = $3;
156: }
157: ;
158:
159: CF_ADDTO(conf, roa_table)
160:
161: roa_table_start: ROA TABLE SYM {
162: this_roa_table = roa_new_table_config($3);
163: };
164:
165: roa_table_opts:
166: /* empty */
167: | roa_table_opts ROA prefix MAX NUM AS NUM ';' {
168: roa_add_item_config(this_roa_table, $3.addr, $3.len, $5, $7);
169: }
170: ;
171:
172: roa_table:
173: roa_table_start
174: | roa_table_start '{' roa_table_opts '}'
175: ;
176:
177: /* Definition of protocols */
178:
179: CF_ADDTO(conf, proto)
180:
181: proto_start:
182: PROTOCOL { $$ = SYM_PROTO; }
183: | TEMPLATE { $$ = SYM_TEMPLATE; }
184: ;
185:
186: proto_name:
187: /* EMPTY */ {
188: struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
189: s->class = this_proto->class;
190: s->def = this_proto;
191: this_proto->name = s->name;
192: }
193: | SYM {
194: cf_define_symbol($1, this_proto->class, this_proto);
195: this_proto->name = $1->name;
196: }
197: | FROM SYM {
198: struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
199: s->class = this_proto->class;
200: s->def = this_proto;
201: this_proto->name = s->name;
202:
203: if (($2->class != SYM_TEMPLATE) && ($2->class != SYM_PROTO)) cf_error("Template or protocol name expected");
204: proto_copy_config(this_proto, $2->def);
205: }
206: | SYM FROM SYM {
207: cf_define_symbol($1, this_proto->class, this_proto);
208: this_proto->name = $1->name;
209:
210: if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
211: proto_copy_config(this_proto, $3->def);
212: }
213: ;
214:
215: proto_item:
216: /* EMPTY */
217: | PREFERENCE expr {
218: if ($2 < 0 || $2 > 0xFFFF) cf_error("Invalid preference");
219: this_proto->preference = $2;
220: }
221: | DISABLED bool { this_proto->disabled = $2; }
222: | DEBUG debug_mask { this_proto->debug = $2; }
223: | MRTDUMP mrtdump_mask { this_proto->mrtdump = $2; }
224: | IMPORT imexport { this_proto->in_filter = $2; }
225: | 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: imexport:
236: FILTER filter { $$ = $2; }
237: | where_filter
238: | ALL { $$ = FILTER_ACCEPT; }
239: | NONE { $$ = FILTER_REJECT; }
240: ;
241:
242: limit_action:
243: /* default */ { $$ = PLA_DISABLE; }
244: | ACTION WARN { $$ = PLA_WARN; }
245: | ACTION BLOCK { $$ = PLA_BLOCK; }
246: | ACTION RESTART { $$ = PLA_RESTART; }
247: | ACTION DISABLE { $$ = PLA_DISABLE; }
248: ;
249:
250: limit_spec:
251: expr limit_action {
252: struct proto_limit *l = cfg_allocz(sizeof(struct proto_limit));
253: l->limit = $1;
254: l->action = $2;
255: $$ = l;
256: }
257: | OFF { $$ = NULL; }
258: ;
259:
260: rtable:
261: SYM {
262: if ($1->class != SYM_TABLE) cf_error("Table name expected");
263: $$ = $1->def;
264: }
265: ;
266:
267: CF_ADDTO(conf, debug_default)
268:
269: debug_default:
270: DEBUG PROTOCOLS debug_mask { new_config->proto_default_debug = $3; }
271: | DEBUG COMMANDS expr { new_config->cli_debug = $3; }
272: ;
273:
274: /* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
275:
276: /* Interface patterns */
277:
278: iface_patt_node_init:
279: /* EMPTY */ {
280: struct iface_patt_node *ipn = cfg_allocz(sizeof(struct iface_patt_node));
281: add_tail(&this_ipatt->ipn_list, NODE ipn);
282: this_ipn = ipn;
283: }
284: ;
285:
286: iface_patt_node_body:
287: TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; }
288: | prefix_or_ipa { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; }
289: | TEXT prefix_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; }
290: ;
291:
292: iface_negate:
293: { this_ipn->positive = 1; }
294: | '-' { this_ipn->positive = 0; }
295: ;
296:
297: iface_patt_node:
298: iface_patt_node_init iface_negate iface_patt_node_body
299: ;
300:
301:
302: iface_patt_list:
303: iface_patt_node
304: | iface_patt_list ',' iface_patt_node
305: ;
306:
307: /* For name/mask-only iface patterns */
308: iface_patt_list_nopx: iface_patt_list { iface_patt_check(); }
309:
310: iface_patt_init: {
311: /* Generic this_ipatt init */
312: this_ipatt = cfg_allocz(sizeof(struct iface_patt));
313: init_list(&this_ipatt->ipn_list);
314: }
315: ;
316:
317: iface_patt:
318: iface_patt_init iface_patt_list
319: ;
320:
321: tos:
322: CLASS expr { $$ = $2 & 0xfc; if (($2 < 0) || ($2 > 255)) cf_error("TX class must be in range 0-255"); }
323: | DSCP expr { $$ = ($2 & 0x3f) << 2; if (($2 < 0) || ($2 > 63)) cf_error("TX DSCP must be in range 0-63"); }
324: ;
325:
326: /* Direct device route protocol */
327:
328: CF_ADDTO(proto, dev_proto '}')
329:
330: dev_proto_start: proto_start DIRECT {
331: this_proto = proto_config_new(&proto_device, $1);
332: init_list(&DIRECT_CFG->iface_list);
333: }
334: ;
335:
336: dev_proto:
337: dev_proto_start proto_name '{'
338: | dev_proto proto_item ';'
339: | dev_proto dev_iface_patt ';'
340: | dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
341: ;
342:
343: dev_iface_init:
344: /* EMPTY */ {
345: this_ipatt = cfg_allocz(sizeof(struct iface_patt));
346: add_tail(&DIRECT_CFG->iface_list, NODE this_ipatt);
347: init_list(&this_ipatt->ipn_list);
348: }
349: ;
350:
351: dev_iface_patt:
352: INTERFACE dev_iface_init iface_patt_list
353: ;
354:
355: /* Debug flags */
356:
357: debug_mask:
358: ALL { $$ = ~0; }
359: | OFF { $$ = 0; }
360: | '{' debug_list '}' { $$ = $2; }
361: ;
362:
363: debug_list:
364: debug_flag
365: | debug_list ',' debug_flag { $$ = $1 | $3; }
366: ;
367:
368: debug_flag:
369: STATES { $$ = D_STATES; }
370: | ROUTES { $$ = D_ROUTES; }
371: | FILTERS { $$ = D_FILTERS; }
372: | INTERFACES { $$ = D_IFACES; }
373: | EVENTS { $$ = D_EVENTS; }
374: | PACKETS { $$ = D_PACKETS; }
375: ;
376:
377: /* MRTDump flags */
378:
379: mrtdump_mask:
380: ALL { $$ = ~0; }
381: | OFF { $$ = 0; }
382: | '{' mrtdump_list '}' { $$ = $2; }
383: ;
384:
385: mrtdump_list:
386: mrtdump_flag
387: | mrtdump_list ',' mrtdump_flag { $$ = $1 | $3; }
388: ;
389:
390: mrtdump_flag:
391: STATES { $$ = MD_STATES; }
392: | MESSAGES { $$ = MD_MESSAGES; }
393: ;
394:
395: /* Password lists */
396:
397: password_list:
398: PASSWORDS '{' password_items '}'
399: | password_item
400: ;
401:
402: password_items:
403: /* empty */
404: | password_item ';' password_items
405: ;
406:
407: password_item:
408: password_item_begin '{' password_item_params '}'
409: | password_item_begin
410: ;
411:
412: password_item_begin:
413: PASSWORD text {
414: if (!this_p_list) {
415: this_p_list = cfg_alloc(sizeof(list));
416: init_list(this_p_list);
417: password_id = 1;
418: }
419: this_p_item = cfg_alloc(sizeof (struct password_item));
420: this_p_item->password = $2;
421: this_p_item->length = strlen($2);
422: this_p_item->genfrom = 0;
423: this_p_item->gento = TIME_INFINITY;
424: this_p_item->accfrom = 0;
425: this_p_item->accto = TIME_INFINITY;
426: this_p_item->id = password_id++;
427: this_p_item->alg = ALG_UNDEFINED;
428: add_tail(this_p_list, &this_p_item->n);
429: }
430: ;
431:
432: password_item_params:
433: /* empty */ { }
434: | GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; }
435: | GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; }
436: | ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; }
437: | ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; }
438: | FROM datetime ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
439: | TO datetime ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
440: | ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
441: | ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
442: ;
443:
444: password_algorithm:
445: KEYED MD5 { $$ = ALG_MD5; }
446: | KEYED SHA1 { $$ = ALG_SHA1; }
447: | KEYED SHA256 { $$ = ALG_SHA256; }
448: | KEYED SHA384 { $$ = ALG_SHA384; }
449: | KEYED SHA512 { $$ = ALG_SHA512; }
450: | HMAC MD5 { $$ = ALG_HMAC_MD5; }
451: | HMAC SHA1 { $$ = ALG_HMAC_SHA1; }
452: | HMAC SHA256 { $$ = ALG_HMAC_SHA256; }
453: | HMAC SHA384 { $$ = ALG_HMAC_SHA384; }
454: | HMAC SHA512 { $$ = ALG_HMAC_SHA512; }
455: ;
456:
457: /* Core commands */
458: CF_CLI_HELP(SHOW, ..., [[Show status information]])
459:
460: CF_CLI(SHOW STATUS,,, [[Show router status]])
461: { cmd_show_status(); } ;
462:
463: CF_CLI(SHOW MEMORY,,, [[Show memory usage]])
464: { cmd_show_memory(); } ;
465:
466: CF_CLI(SHOW PROTOCOLS, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocols]])
467: { proto_apply_cmd($3, proto_cmd_show, 0, 0); } ;
468:
469: CF_CLI(SHOW PROTOCOLS ALL, proto_patt2, [<protocol> | \"<pattern>\"], [[Show routing protocol details]])
470: { proto_apply_cmd($4, proto_cmd_show, 0, 1); } ;
471:
472: optsym:
473: SYM
474: | /* empty */ { $$ = NULL; }
475: ;
476:
477: CF_CLI(SHOW INTERFACES,,, [[Show network interfaces]])
478: { if_show(); } ;
479:
480: CF_CLI(SHOW INTERFACES SUMMARY,,, [[Show summary of network interfaces]])
481: { if_show_summary(); } ;
482:
483: CF_CLI_HELP(SHOW ROUTE, ..., [[Show routing table]])
484: 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]])
485: { rt_show($3); } ;
486:
487: r_args:
488: /* empty */ {
489: $$ = cfg_allocz(sizeof(struct rt_show_data));
490: $$->pxlen = 256;
491: $$->filter = FILTER_ACCEPT;
492: }
493: | r_args prefix {
494: $$ = $1;
495: if ($$->pxlen != 256) cf_error("Only one prefix expected");
496: $$->prefix = $2.addr;
497: $$->pxlen = $2.len;
498: }
499: | r_args FOR prefix_or_ipa {
500: $$ = $1;
501: if ($$->pxlen != 256) cf_error("Only one prefix expected");
502: $$->prefix = $3.addr;
503: $$->pxlen = $3.len;
504: $$->show_for = 1;
505: }
506: | r_args TABLE SYM {
507: $$ = $1;
508: if ($3->class != SYM_TABLE) cf_error("%s is not a table", $3->name);
509: $$->table = ((struct rtable_config *)$3->def)->table;
510: }
511: | r_args FILTER filter {
512: $$ = $1;
513: if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
514: $$->filter = $3;
515: }
516: | r_args where_filter {
517: $$ = $1;
518: if ($$->filter != FILTER_ACCEPT) cf_error("Filter specified twice");
519: $$->filter = $2;
520: }
521: | r_args ALL {
522: $$ = $1;
523: $$->verbose = 1;
524: }
525: | r_args PRIMARY {
526: $$ = $1;
527: $$->primary_only = 1;
528: }
529: | r_args FILTERED {
530: $$ = $1;
531: $$->filtered = 1;
532: }
533: | r_args export_mode SYM {
534: struct proto_config *c = (struct proto_config *) $3->def;
535: $$ = $1;
536: if ($$->export_mode) cf_error("Protocol specified twice");
537: if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
538: $$->export_mode = $2;
539: $$->export_protocol = c->proto;
540: $$->running_on_config = c->proto->cf->global;
541: }
542: | r_args PROTOCOL SYM {
543: struct proto_config *c = (struct proto_config *) $3->def;
544: $$ = $1;
545: if ($$->show_protocol) cf_error("Protocol specified twice");
546: if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
547: $$->show_protocol = c->proto;
548: $$->running_on_config = c->proto->cf->global;
549: }
550: | r_args STATS {
551: $$ = $1;
552: $$->stats = 1;
553: }
554: | r_args COUNT {
555: $$ = $1;
556: $$->stats = 2;
557: }
558: ;
559:
560: export_mode:
561: PREEXPORT { $$ = RSEM_PREEXPORT; }
562: | EXPORT { $$ = RSEM_EXPORT; }
563: | NOEXPORT { $$ = RSEM_NOEXPORT; }
564: ;
565:
566:
567: CF_CLI_HELP(SHOW ROA, ..., [[Show ROA table]])
568: CF_CLI(SHOW ROA, roa_args, [<prefix> | in <prefix> | for <prefix>] [as <num>] [table <t>], [[Show ROA table]])
569: { roa_show($3); } ;
570:
571: roa_args:
572: /* empty */ {
573: $$ = cfg_allocz(sizeof(struct roa_show_data));
574: $$->mode = ROA_SHOW_ALL;
575: $$->table = roa_table_default;
576: if (roa_table_default == NULL)
577: cf_error("No ROA table defined");
578: }
579: | roa_args roa_mode prefix {
580: $$ = $1;
581: if ($$->mode != ROA_SHOW_ALL) cf_error("Only one prefix expected");
582: $$->prefix = $3.addr;
583: $$->pxlen = $3.len;
584: $$->mode = $2;
585: }
586: | roa_args AS NUM {
587: $$ = $1;
588: $$->asn = $3;
589: }
590: | roa_args TABLE SYM {
591: $$ = $1;
592: if ($3->class != SYM_ROA) cf_error("%s is not a ROA table", $3->name);
593: $$->table = ((struct roa_table_config *)$3->def)->table;
594: }
595: ;
596:
597: roa_mode:
598: { $$ = ROA_SHOW_PX; }
599: | IN { $$ = ROA_SHOW_IN; }
600: | FOR { $$ = ROA_SHOW_FOR; }
601: ;
602:
603:
604: CF_CLI_HELP(SHOW SYMBOLS, ..., [[Show all known symbolic names]])
605: CF_CLI(SHOW SYMBOLS, sym_args, [table|filter|function|protocol|template|roa|<symbol>], [[Show all known symbolic names]])
606: { cmd_show_symbols($3); } ;
607:
608: sym_args:
609: /* empty */ {
610: $$ = cfg_allocz(sizeof(struct sym_show_data));
611: }
612: | sym_args TABLE { $$ = $1; $$->type = SYM_TABLE; }
613: | sym_args FUNCTION { $$ = $1; $$->type = SYM_FUNCTION; }
614: | sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
615: | sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
616: | sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
617: | sym_args ROA { $$ = $1; $$->type = SYM_ROA; }
618: | sym_args SYM { $$ = $1; $$->sym = $2; }
619: ;
620:
621:
622: roa_table_arg:
623: /* empty */ {
624: if (roa_table_default == NULL)
625: cf_error("No ROA table defined");
626: $$ = roa_table_default;
627: }
628: | TABLE SYM {
629: if ($2->class != SYM_ROA)
630: cf_error("%s is not a ROA table", $2->name);
631: $$ = ((struct roa_table_config *)$2->def)->table;
632: }
633: ;
634:
635: CF_CLI_HELP(ADD, roa ..., [[Add ROA record]])
636: CF_CLI(ADD ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Add ROA record]])
637: {
638: if (! cli_access_restricted())
639: { roa_add_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
640: };
641:
642: CF_CLI_HELP(DELETE, roa ..., [[Delete ROA record]])
643: CF_CLI(DELETE ROA, prefix MAX NUM AS NUM roa_table_arg, <prefix> max <num> as <num> [table <name>], [[Delete ROA record]])
644: {
645: if (! cli_access_restricted())
646: { roa_delete_item($8, $3.addr, $3.len, $5, $7, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
647: };
648:
649: CF_CLI_HELP(FLUSH, roa [table <name>], [[Removes all dynamic ROA records]])
650: CF_CLI(FLUSH ROA, roa_table_arg, [table <name>], [[Removes all dynamic ROA records]])
651: {
652: if (! cli_access_restricted())
653: { roa_flush($3, ROA_SRC_DYNAMIC); cli_msg(0, ""); }
654: };
655:
656:
657: CF_CLI_HELP(DUMP, ..., [[Dump debugging information]])
658: CF_CLI(DUMP RESOURCES,,, [[Dump all allocated resource]])
659: { rdump(&root_pool); cli_msg(0, ""); } ;
660: CF_CLI(DUMP SOCKETS,,, [[Dump open sockets]])
661: { sk_dump_all(); cli_msg(0, ""); } ;
662: CF_CLI(DUMP EVENTS,,, [[Dump event log]])
663: { io_log_dump(); cli_msg(0, ""); } ;
664: CF_CLI(DUMP INTERFACES,,, [[Dump interface information]])
665: { if_dump_all(); cli_msg(0, ""); } ;
666: CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
667: { neigh_dump_all(); cli_msg(0, ""); } ;
668: CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
669: { rta_dump_all(); cli_msg(0, ""); } ;
670: CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
671: { rt_dump_all(); cli_msg(0, ""); } ;
672: CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
673: { protos_dump_all(); cli_msg(0, ""); } ;
674:
675: CF_CLI(EVAL, term, <expr>, [[Evaluate an expression]])
676: { cmd_eval($2); } ;
677:
678: CF_CLI_HELP(ECHO, ..., [[Control echoing of log messages]])
679: CF_CLI(ECHO, echo_mask echo_size, (all | off | { debug|trace|info|remote|warning|error|auth [, ...] }) [<buffer-size>], [[Control echoing of log messages]]) {
680: cli_set_log_echo(this_cli, $2, $3);
681: cli_msg(0, "");
682: } ;
683:
684: echo_mask:
685: ALL { $$ = ~0; }
686: | OFF { $$ = 0; }
687: | '{' log_mask_list '}' { $$ = $2; }
688: ;
689:
690: echo_size:
691: /* empty */ { $$ = 4096; }
692: | NUM {
693: if ($1 < 256 || $1 > 65536) cf_error("Invalid log buffer size");
694: $$ = $1;
695: }
696: ;
697:
698: CF_CLI(DISABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Disable protocol]])
699: { proto_apply_cmd($2, proto_cmd_disable, 1, 0); } ;
700: CF_CLI(ENABLE, proto_patt, <protocol> | \"<pattern>\" | all, [[Enable protocol]])
701: { proto_apply_cmd($2, proto_cmd_enable, 1, 0); } ;
702: CF_CLI(RESTART, proto_patt, <protocol> | \"<pattern>\" | all, [[Restart protocol]])
703: { proto_apply_cmd($2, proto_cmd_restart, 1, 0); } ;
704: CF_CLI(RELOAD, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol]])
705: { proto_apply_cmd($2, proto_cmd_reload, 1, CMD_RELOAD); } ;
706: CF_CLI(RELOAD IN, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just imported routes)]])
707: { proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_IN); } ;
708: CF_CLI(RELOAD OUT, proto_patt, <protocol> | \"<pattern>\" | all, [[Reload protocol (just exported routes)]])
709: { proto_apply_cmd($3, proto_cmd_reload, 1, CMD_RELOAD_OUT); } ;
710:
711: CF_CLI_HELP(DEBUG, ..., [[Control protocol debugging via BIRD logs]])
712: CF_CLI(DEBUG, proto_patt debug_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|routes|filters|interfaces|events|packets [, ...] }), [[Control protocol debugging via BIRD logs]])
713: { proto_apply_cmd($2, proto_cmd_debug, 1, $3); } ;
714:
715: CF_CLI_HELP(MRTDUMP, ..., [[Control protocol debugging via MRTdump files]])
716: CF_CLI(MRTDUMP, proto_patt mrtdump_mask, (<protocol> | \"<pattern>\" | all) (all | off | { states|messages [, ...] }), [[Control protocol debugging via MRTdump format]])
717: { proto_apply_cmd($2, proto_cmd_mrtdump, 1, $3); } ;
718:
719: CF_CLI(RESTRICT,,,[[Restrict current CLI session to safe commands]])
720: { this_cli->restricted = 1; cli_msg(16, "Access restricted"); } ;
721:
722: proto_patt:
723: SYM { $$.ptr = $1; $$.patt = 0; }
724: | ALL { $$.ptr = NULL; $$.patt = 1; }
725: | TEXT { $$.ptr = $1; $$.patt = 1; }
726: ;
727:
728: proto_patt2:
729: SYM { $$.ptr = $1; $$.patt = 0; }
730: | { $$.ptr = NULL; $$.patt = 1; }
731: | TEXT { $$.ptr = $1; $$.patt = 1; }
732: ;
733:
734: CF_ADDTO(dynamic_attr, IGP_METRIC
735: { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_GEN_IGP_METRIC); })
736:
737:
738: CF_CODE
739:
740: CF_END
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>