]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/confbase.Y
BFD: Add arguments to 'show bfd sessions' command
[thirdparty/bird.git] / conf / confbase.Y
CommitLineData
f142750d
MM
1/*
2 * BIRD -- Configuration Parser Top
3 *
aee539f2 4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
f142750d
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9CF_HDR
10
93e868c7
OZ
11#define PARSER 1
12
f142750d
MM
13#include "nest/bird.h"
14#include "conf/conf.h"
c74c0e3c
MM
15#include "lib/resource.h"
16#include "lib/socket.h"
f047271c 17#include "lib/timer.h"
221135d6 18#include "lib/string.h"
c74c0e3c 19#include "nest/protocol.h"
50d8424a 20#include "nest/iface.h"
166b9c49 21#include "nest/route.h"
9d3fc306 22#include "nest/bfd.h"
bc2fb680 23#include "nest/cli.h"
b9d70dc8 24#include "filter/filter.h"
f142750d 25
f2c6c80a
MM
26/* FIXME: Turn on YYERROR_VERBOSE and work around lots of bison bugs? */
27
b8cc390e
OZ
28CF_DEFINES
29
30static void
6aaaa635 31check_u16(uint val)
b8cc390e
OZ
32{
33 if (val > 0xFFFF)
6aaaa635 34 cf_error("Value %u out of range (0-65535)", val);
b8cc390e
OZ
35}
36
9eef9c64
MM
37#define cf_assert(cond, ...) do { if (!(cond)) cf_error(__VA_ARGS__); } while (0)
38static inline void cf_assert_symbol(const struct symbol *sym, uint class) {
39 switch (class) {
40 case SYM_PROTO: cf_assert(sym->class == SYM_PROTO, "Protocol name required"); break;
41 case SYM_TEMPLATE: cf_assert(sym->class == SYM_TEMPLATE, "Protocol template name required"); break;
42 case SYM_FUNCTION: cf_assert(sym->class == SYM_FUNCTION, "Function name required"); break;
43 case SYM_FILTER: cf_assert(sym->class == SYM_FILTER, "Filter name required"); break;
44 case SYM_TABLE: cf_assert(sym->class == SYM_TABLE, "Table name required"); break;
45 case SYM_ATTRIBUTE: cf_assert(sym->class == SYM_ATTRIBUTE, "Custom attribute name required"); break;
333ddd4f
OZ
46 case SYM_MPLS_DOMAIN: cf_assert(sym->class == SYM_MPLS_DOMAIN, "MPLS domain name required"); break;
47 case SYM_MPLS_RANGE: cf_assert(sym->class == SYM_MPLS_RANGE, "MPLS range name required"); break;
9eef9c64
MM
48 case SYM_VARIABLE: cf_assert((sym->class & ~0xff) == SYM_VARIABLE, "Variable name required"); break;
49 case SYM_CONSTANT: cf_assert((sym->class & ~0xff) == SYM_CONSTANT, "Constant name required"); break;
50 default: bug("This shall not happen");
51 }
52}
53
f142750d
MM
54CF_DECLS
55
56%union {
6aaaa635 57 uint i;
dce26783 58 u32 i32;
d311368b 59 u64 i64;
f142750d 60 ip_addr a;
fe9f1a6d
OZ
61 ip4_addr ip4;
62 ip6_addr ip6;
04632fd7 63 net_addr net;
d44e686e 64 net_addr *net_ptr;
f142750d 65 struct symbol *s;
a8a64ca0 66 struct keyword *kw;
fd9f0c06 67 const char *t;
0e02abfd 68 struct rtable_config *r;
f4a60a9b 69 struct channel_config *cc;
61dae32b 70 struct channel *c;
e0f2e42f 71 struct f_inst *x;
0206c070
MM
72 struct {
73 struct f_inst *begin, *end;
74 } xp;
9b46748d
MM
75 enum filter_return fret;
76 enum ec_subtype ecs;
5a14df39
MM
77 struct f_dynamic_attr fda;
78 struct f_static_attr fsa;
c0e958e0 79 struct f_lval flv;
96d757c1 80 struct f_line *fl;
93d6096c 81 struct f_arg *fa;
0b39b1cb 82 const struct filter *f;
38506f71 83 struct f_tree *e;
b1a597e0 84 struct f_trie *trie;
38506f71 85 struct f_val v;
9d79fec8 86 struct password_item *p;
730f2e2c 87 struct rt_show_data *ra;
0f808c06 88 struct sym_show_data *sd;
20ab192b 89 struct lsadb_show_data *ld;
863ecfc7 90 struct mrt_dump_data *md;
8e9e013b 91 struct mpls_show_ranges_cmd *msrc;
26dd61ee 92 struct bfd_show_sessions_cmd *bssc;
69a8259c 93 struct iface *iface;
4ab5331c 94 void *g;
f047271c 95 btime time;
5e173e9f 96 struct f_prefix px;
e304fd4b 97 struct proto_spec ps;
f4a60a9b 98 struct channel_limit cl;
c37e7851 99 struct timeformat *tf;
3c744164 100 mpls_label_stack *mls;
bb8e2824 101 const struct adata *bs;
977b82fb 102 struct aggr_item_node *ai;
f142750d
MM
103}
104
b8cc390e 105%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
fc4398b4 106%token GEQ LEQ NEQ AND OR IMP
cf186034 107%token PO PC
944f008a 108%token <i> NUM ENUM
fe9f1a6d
OZ
109%token <ip4> IP4
110%token <ip6> IP6
d311368b 111%token <i64> VPN_RD
fc9d471b 112%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
f142750d 113%token <t> TEXT
fc354788 114%token <bs> BYTETEXT
69a8259c 115%type <iface> ipa_scope
f142750d 116
04632fd7 117%type <i> expr bool pxlen4
ee528fbd 118%type <time> expr_us time
04632fd7 119%type <a> ipa
141fb51f 120%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
be17805c 121%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
3c744164 122%type <mls> label_stack_start label_stack
d44e686e
OZ
123
124%type <t> text opttext
f411a19b 125%type <bs> bytestring
8e177cf3 126%type <s> symbol symbol_known
0b62c3a7 127
116285f2 128%type <v> bytestring_text text_or_ipa
f411a19b
OZ
129%type <x> bytestring_expr
130
60de3356 131%nonassoc PREFIX_DUMMY
1960d203 132%left AND OR
fc4398b4 133%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA IMP PO PC
1960d203 134%left '+' '-'
0b62c3a7 135%left '*' '/' '%'
23b1539b 136%left '!'
112d71a7 137%nonassoc '.'
0b62c3a7 138
9eef9c64
MM
139%start config
140
f86c86b7 141CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS)
0b62c3a7 142
f142750d
MM
143CF_GRAMMAR
144
0b62c3a7
MM
145/* Basic config file structure */
146
bc2fb680 147config: conf_entries END { return 0; }
ffb59d24 148 | CLI_MARKER cli_cmd { return 0; }
f142750d
MM
149 ;
150
151conf_entries:
152 /* EMPTY */
7f400d1c 153 | conf_entries conf
f142750d
MM
154 ;
155
f851f0d7 156conf: ';' ;
f142750d 157
1103b32e 158
72380a34 159/* Constant expressions */
0b62c3a7 160
f851f0d7
MM
161conf: definition ;
162
1103b32e 163definition:
2de1e206 164 DEFINE symbol '=' term ';' {
30b84682 165 struct f_val *val = cfg_allocz(sizeof(struct f_val));
0dbcc927 166 *val = cf_eval($4, T_VOID);
51f2e7af 167 cf_define_symbol(new_config, $2, SYM_CONSTANT | val->type, val, val);
1103b32e
OZ
168 }
169 ;
170
c9b66706 171expr:
0b62c3a7 172 NUM
0dbcc927 173 | '(' term ')' { $$ = cf_eval_int($2); }
8e177cf3 174 | symbol_known {
9eef9c64 175 if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
1103b32e 176 $$ = SYM_VAL($1).i; }
0b62c3a7
MM
177 ;
178
6a8d3f1c 179expr_us:
ee528fbd
OZ
180 expr S { $$ = $1 S_; }
181 | expr MS { $$ = $1 MS_; }
182 | expr US { $$ = $1 US_; }
6a8d3f1c
OZ
183 ;
184
8e177cf3 185symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | KEYWORD ;
c0231b09 186symbol_known: CF_SYM_KNOWN ;
c0e958e0 187
166b9c49
MM
188/* Switches */
189
190bool:
c8cafc8e 191 expr { $$ = !!$1; }
166b9c49
MM
192 | ON { $$ = 1; }
193 | YES { $$ = 1; }
194 | OFF { $$ = 0; }
195 | NO { $$ = 0; }
196 | /* Silence means agreement */ { $$ = 1; }
197 ;
198
e3f2d5fc 199
04632fd7 200/* Addresses */
fe9f1a6d 201
e3f2d5fc 202ipa:
04632fd7
OZ
203 IP4 { $$ = ipa_from_ip4($1); }
204 | IP6 { $$ = ipa_from_ip6($1); }
9eef9c64
MM
205 | CF_SYM_KNOWN {
206 if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address constant expected");
5e173e9f 207 $$ = SYM_VAL($1).ip;
e3f2d5fc
MM
208 }
209 ;
89d2355d 210
69a8259c
OZ
211ipa_scope:
212 /* empty */ { $$ = NULL; }
c0e958e0 213 | '%' symbol { $$ = if_get_by_name($2->name); }
69a8259c
OZ
214 ;
215
d44e686e 216
04632fd7 217/* Networks - internal */
d44e686e 218
04632fd7
OZ
219pxlen4:
220 '/' NUM {
6aaaa635 221 if ($2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %u", $2);
04632fd7
OZ
222 $$ = $2;
223 }
04632fd7 224 ;
d44e686e 225
04632fd7
OZ
226net_ip4_: IP4 pxlen4
227{
228 net_fill_ip4(&($$), $1, $2);
0705a1c5
PT
229
230 net_addr_ip4 *n = (void *) &($$);
231 if (!net_validate_ip4(n))
232 cf_error("Invalid IPv4 prefix %I4/%d, maybe you wanted %I4/%d",
233 n->prefix, n->pxlen, ip4_and(n->prefix, ip4_mkmask(n->pxlen)), n->pxlen);
04632fd7 234};
d44e686e 235
04632fd7
OZ
236net_ip6_: IP6 '/' NUM
237{
6aaaa635
OZ
238 if ($3 > IP6_MAX_PREFIX_LENGTH)
239 cf_error("Invalid prefix length %u", $3);
0705a1c5
PT
240
241 net_fill_ip6(&($$), $1, $3);
242
243 net_addr_ip6 *n = (void *) &($$);
244 if (!net_validate_ip6(n))
245 cf_error("Invalid IPv6 prefix %I6/%d, maybe you wanted %I6/%d",
246 n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
04632fd7 247};
d44e686e 248
be17805c
OZ
249net_ip6_sadr_: IP6 '/' NUM FROM IP6 '/' NUM
250{
251 if ($3 > IP6_MAX_PREFIX_LENGTH)
252 cf_error("Invalid prefix length %u", $3);
253
254 if ($7 > IP6_MAX_PREFIX_LENGTH)
255 cf_error("Invalid prefix length %u", $7);
256
257 $$ = cfg_alloc(sizeof(net_addr_ip6_sadr));
258 net_fill_ip6_sadr($$, $1, $3, $5, $7);
259
260 net_addr_ip6_sadr *n = (void *) $$;
261 if (!net_validate_ip6_sadr(n))
262 cf_error("Invalid SADR IPv6 prefix %I6/%d from %I6/%d, maybe you wanted %I6/%d from %I6/%d",
263 n->dst_prefix, n->dst_pxlen, n->src_prefix, n->src_pxlen,
264 ip6_and(n->dst_prefix, ip6_mkmask(n->dst_pxlen)), n->dst_pxlen,
265 ip6_and(n->src_prefix, ip6_mkmask(n->src_pxlen)), n->src_pxlen);
266};
267
d311368b
MM
268net_vpn4_: VPN_RD net_ip4_
269{
270 $$ = cfg_alloc(sizeof(net_addr_vpn4));
62e64905 271 net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
d311368b
MM
272}
273
274net_vpn6_: VPN_RD net_ip6_
275{
276 $$ = cfg_alloc(sizeof(net_addr_vpn6));
62e64905 277 net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
d311368b
MM
278}
279
513ad0a8
PT
280net_roa4_: net_ip4_ MAX NUM AS NUM
281{
a4caa1c0 282 $$ = cfg_alloc(sizeof(net_addr_roa4));
286e2011 283 net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
6aaaa635
OZ
284 if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
285 cf_error("Invalid max prefix length %u", $3);
513ad0a8
PT
286};
287
288net_roa6_: net_ip6_ MAX NUM AS NUM
289{
a4caa1c0 290 $$ = cfg_alloc(sizeof(net_addr_roa6));
286e2011 291 net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
6aaaa635
OZ
292 if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
293 cf_error("Invalid max prefix length %u", $3);
513ad0a8
PT
294};
295
66acbc8d
OZ
296net_mpls_: MPLS NUM
297{
a740054d 298 $$ = cfg_alloc(sizeof(net_addr_mpls));
66acbc8d
OZ
299 net_fill_mpls($$, $2);
300}
301
04632fd7 302net_ip_: net_ip4_ | net_ip6_ ;
d311368b 303net_vpn_: net_vpn4_ | net_vpn6_ ;
62e64905 304net_roa_: net_roa4_ | net_roa6_ ;
513ad0a8 305
a4caa1c0
PT
306net_:
307 net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
d311368b 308 | net_vpn_
a4caa1c0 309 | net_roa_
77234bbb 310 | net_flow_
be17805c 311 | net_ip6_sadr_
66acbc8d 312 | net_mpls_
a4caa1c0 313 ;
d44e686e
OZ
314
315
04632fd7
OZ
316/* Networks - regular */
317
141fb51f
MM
318net_ip4:
319 net_ip4_
320 | CF_SYM_KNOWN {
321 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP4))
322 cf_error("IPv4 network constant expected");
323 $$ = * SYM_VAL($1).net;
324 }
325 ;
326
04632fd7
OZ
327net_ip6:
328 net_ip6_
9eef9c64 329 | CF_SYM_KNOWN {
04632fd7 330 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
9eef9c64 331 cf_error("IPv6 network constant expected");
04632fd7 332 $$ = * SYM_VAL($1).net;
d7661fbe 333 }
04632fd7
OZ
334 ;
335
336net_ip:
337 net_ip_
9eef9c64 338 | CF_SYM_KNOWN {
04632fd7 339 if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
9eef9c64 340 cf_error("IP network constant expected");
04632fd7 341 $$ = * SYM_VAL($1).net;
758458be
MM
342 }
343 ;
344
04632fd7
OZ
345net_any:
346 net_
9eef9c64 347 | CF_SYM_KNOWN {
04632fd7 348 if ($1->class != (SYM_CONSTANT | T_NET))
9eef9c64 349 cf_error("Network constant expected");
04632fd7
OZ
350 $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
351 }
352 ;
353
354net_or_ipa:
355 net_ip4_
356 | net_ip6_
357 | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
358 | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
9eef9c64 359 | CF_SYM_KNOWN {
04632fd7
OZ
360 if ($1->class == (SYM_CONSTANT | T_IP))
361 net_fill_ip_host(&($$), SYM_VAL($1).ip);
362 else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
363 $$ = * SYM_VAL($1).net;
364 else
9eef9c64 365 cf_error("IP address or network constant expected");
89d2355d 366 }
89d2355d
MM
367 ;
368
f2010f9c
MM
369label_stack_start: NUM
370{
3c744164
MM
371 $$ = cfg_allocz(sizeof(mpls_label_stack));
372 $$->len = 1;
373 $$->stack[0] = $1;
f2010f9c
MM
374};
375
376label_stack:
377 label_stack_start
378 | label_stack '/' NUM {
3c744164 379 if ($1->len >= MPLS_MAX_LABEL_STACK)
62e64905 380 cf_error("Too many labels in stack");
3c744164 381 $1->stack[$1->len++] = $3;
f2010f9c
MM
382 $$ = $1;
383 }
384;
04632fd7 385
f047271c 386time:
aee539f2 387 TEXT {
f047271c 388 $$ = tm_parse_time($1);
aee539f2 389 if (!$$)
f047271c 390 cf_error("Invalid date/time");
aee539f2 391 }
9d79fec8
PM
392 ;
393
9eceab33
OZ
394text:
395 TEXT
9eef9c64
MM
396 | CF_SYM_KNOWN {
397 if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String constant expected");
9eceab33
OZ
398 $$ = SYM_VAL($1).s;
399 }
400 ;
401
fe9f1a6d
OZ
402opttext:
403 TEXT
404 | /* empty */ { $$ = NULL; }
405 ;
406
116285f2
OZ
407text_or_ipa:
408 TEXT { $$.type = T_STRING; $$.val.s = $1; }
409 | IP4 { $$.type = T_IP; $$.val.ip = ipa_from_ip4($1); }
410 | IP6 { $$.type = T_IP; $$.val.ip = ipa_from_ip6($1); }
411 | CF_SYM_KNOWN {
412 if (($1->class == (SYM_CONSTANT | T_STRING)) ||
413 ($1->class == (SYM_CONSTANT | T_IP)))
414 $$ = *($1->val);
415 else
416 cf_error("String or IP constant expected");
417 }
418 | '(' term ')' {
419 $$ = cf_eval($2, T_VOID);
420 if (($$.type != T_BYTESTRING) && ($$.type != T_STRING))
421 cf_error("Bytestring or string value expected");
422 }
423 ;
424
f411a19b
OZ
425bytestring:
426 BYTETEXT
427 | bytestring_expr { $$ = cf_eval($1, T_BYTESTRING).val.bs; }
428 ;
429
430bytestring_text:
431 BYTETEXT { $$.type = T_BYTESTRING; $$.val.bs = $1; }
432 | TEXT { $$.type = T_STRING; $$.val.s = $1; }
433 | bytestring_expr {
434 $$ = cf_eval($1, T_VOID);
435 if (($$.type != T_BYTESTRING) && ($$.type != T_STRING))
436 cf_error("Bytestring or string value expected");
437 }
438 ;
439
440bytestring_expr:
441 symbol_value
442 | term_bs
443 | '(' term ')' { $$ = $2; }
444 ;
445
fe9f1a6d 446
f142750d
MM
447CF_CODE
448
449CF_END