]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/confbase.Y
MPLS: Add command 'show mpls ranges'
[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
MJM
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;
69a8259c 92 struct iface *iface;
4ab5331c 93 void *g;
f047271c 94 btime time;
5e173e9f 95 struct f_prefix px;
e304fd4b 96 struct proto_spec ps;
f4a60a9b 97 struct channel_limit cl;
c37e7851 98 struct timeformat *tf;
3c744164 99 mpls_label_stack *mls;
bb8e2824 100 const struct adata *bs;
977b82fb 101 struct aggr_item_node *ai;
f142750d
MM
102}
103
b8cc390e 104%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
fc4398b4 105%token GEQ LEQ NEQ AND OR IMP
cf186034 106%token PO PC
944f008a 107%token <i> NUM ENUM
fe9f1a6d
OZ
108%token <ip4> IP4
109%token <ip6> IP6
d311368b 110%token <i64> VPN_RD
fc9d471b 111%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
f142750d 112%token <t> TEXT
fc354788 113%token <bs> BYTETEXT
69a8259c 114%type <iface> ipa_scope
f142750d 115
04632fd7 116%type <i> expr bool pxlen4
ee528fbd 117%type <time> expr_us time
04632fd7 118%type <a> ipa
141fb51f 119%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
be17805c 120%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
3c744164 121%type <mls> label_stack_start label_stack
d44e686e
OZ
122
123%type <t> text opttext
f411a19b 124%type <bs> bytestring
8e177cf3 125%type <s> symbol symbol_known
0b62c3a7 126
116285f2 127%type <v> bytestring_text text_or_ipa
f411a19b
OZ
128%type <x> bytestring_expr
129
60de3356 130%nonassoc PREFIX_DUMMY
1960d203 131%left AND OR
fc4398b4 132%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA IMP PO PC
1960d203 133%left '+' '-'
0b62c3a7 134%left '*' '/' '%'
23b1539b 135%left '!'
112d71a7 136%nonassoc '.'
0b62c3a7 137
9eef9c64
MM
138%start config
139
f86c86b7 140CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS)
0b62c3a7 141
f142750d
MM
142CF_GRAMMAR
143
0b62c3a7
MM
144/* Basic config file structure */
145
bc2fb680 146config: conf_entries END { return 0; }
ffb59d24 147 | CLI_MARKER cli_cmd { return 0; }
f142750d
MM
148 ;
149
150conf_entries:
151 /* EMPTY */
7f400d1c 152 | conf_entries conf
f142750d
MM
153 ;
154
f851f0d7 155conf: ';' ;
f142750d 156
1103b32e 157
72380a34 158/* Constant expressions */
0b62c3a7 159
f851f0d7
JMM
160conf: definition ;
161
1103b32e 162definition:
2de1e206 163 DEFINE symbol '=' term ';' {
30b84682 164 struct f_val *val = cfg_allocz(sizeof(struct f_val));
0dbcc927 165 *val = cf_eval($4, T_VOID);
51f2e7af 166 cf_define_symbol(new_config, $2, SYM_CONSTANT | val->type, val, val);
1103b32e
OZ
167 }
168 ;
169
c9b66706 170expr:
0b62c3a7 171 NUM
0dbcc927 172 | '(' term ')' { $$ = cf_eval_int($2); }
8e177cf3 173 | symbol_known {
9eef9c64 174 if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
1103b32e 175 $$ = SYM_VAL($1).i; }
0b62c3a7
MM
176 ;
177
6a8d3f1c 178expr_us:
ee528fbd
OZ
179 expr S { $$ = $1 S_; }
180 | expr MS { $$ = $1 MS_; }
181 | expr US { $$ = $1 US_; }
6a8d3f1c
OZ
182 ;
183
8e177cf3 184symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | KEYWORD ;
c0231b09 185symbol_known: CF_SYM_KNOWN ;
c0e958e0 186
166b9c49
MM
187/* Switches */
188
189bool:
c8cafc8e 190 expr { $$ = !!$1; }
166b9c49
MM
191 | ON { $$ = 1; }
192 | YES { $$ = 1; }
193 | OFF { $$ = 0; }
194 | NO { $$ = 0; }
195 | /* Silence means agreement */ { $$ = 1; }
196 ;
197
e3f2d5fc 198
04632fd7 199/* Addresses */
fe9f1a6d 200
e3f2d5fc 201ipa:
04632fd7
OZ
202 IP4 { $$ = ipa_from_ip4($1); }
203 | IP6 { $$ = ipa_from_ip6($1); }
9eef9c64
MM
204 | CF_SYM_KNOWN {
205 if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address constant expected");
5e173e9f 206 $$ = SYM_VAL($1).ip;
e3f2d5fc
MM
207 }
208 ;
89d2355d 209
69a8259c
OZ
210ipa_scope:
211 /* empty */ { $$ = NULL; }
c0e958e0 212 | '%' symbol { $$ = if_get_by_name($2->name); }
69a8259c
OZ
213 ;
214
d44e686e 215
04632fd7 216/* Networks - internal */
d44e686e 217
04632fd7
OZ
218pxlen4:
219 '/' NUM {
6aaaa635 220 if ($2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %u", $2);
04632fd7
OZ
221 $$ = $2;
222 }
04632fd7 223 ;
d44e686e 224
04632fd7
OZ
225net_ip4_: IP4 pxlen4
226{
227 net_fill_ip4(&($$), $1, $2);
0705a1c5
PT
228
229 net_addr_ip4 *n = (void *) &($$);
230 if (!net_validate_ip4(n))
231 cf_error("Invalid IPv4 prefix %I4/%d, maybe you wanted %I4/%d",
232 n->prefix, n->pxlen, ip4_and(n->prefix, ip4_mkmask(n->pxlen)), n->pxlen);
04632fd7 233};
d44e686e 234
04632fd7
OZ
235net_ip6_: IP6 '/' NUM
236{
6aaaa635
OZ
237 if ($3 > IP6_MAX_PREFIX_LENGTH)
238 cf_error("Invalid prefix length %u", $3);
0705a1c5
PT
239
240 net_fill_ip6(&($$), $1, $3);
241
242 net_addr_ip6 *n = (void *) &($$);
243 if (!net_validate_ip6(n))
244 cf_error("Invalid IPv6 prefix %I6/%d, maybe you wanted %I6/%d",
245 n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
04632fd7 246};
d44e686e 247
be17805c
OZ
248net_ip6_sadr_: IP6 '/' NUM FROM IP6 '/' NUM
249{
250 if ($3 > IP6_MAX_PREFIX_LENGTH)
251 cf_error("Invalid prefix length %u", $3);
252
253 if ($7 > IP6_MAX_PREFIX_LENGTH)
254 cf_error("Invalid prefix length %u", $7);
255
256 $$ = cfg_alloc(sizeof(net_addr_ip6_sadr));
257 net_fill_ip6_sadr($$, $1, $3, $5, $7);
258
259 net_addr_ip6_sadr *n = (void *) $$;
260 if (!net_validate_ip6_sadr(n))
261 cf_error("Invalid SADR IPv6 prefix %I6/%d from %I6/%d, maybe you wanted %I6/%d from %I6/%d",
262 n->dst_prefix, n->dst_pxlen, n->src_prefix, n->src_pxlen,
263 ip6_and(n->dst_prefix, ip6_mkmask(n->dst_pxlen)), n->dst_pxlen,
264 ip6_and(n->src_prefix, ip6_mkmask(n->src_pxlen)), n->src_pxlen);
265};
266
d311368b
JMM
267net_vpn4_: VPN_RD net_ip4_
268{
269 $$ = cfg_alloc(sizeof(net_addr_vpn4));
62e64905 270 net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
d311368b
JMM
271}
272
273net_vpn6_: VPN_RD net_ip6_
274{
275 $$ = cfg_alloc(sizeof(net_addr_vpn6));
62e64905 276 net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
d311368b
JMM
277}
278
513ad0a8
PT
279net_roa4_: net_ip4_ MAX NUM AS NUM
280{
a4caa1c0 281 $$ = cfg_alloc(sizeof(net_addr_roa4));
286e2011 282 net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
6aaaa635
OZ
283 if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
284 cf_error("Invalid max prefix length %u", $3);
513ad0a8
PT
285};
286
287net_roa6_: net_ip6_ MAX NUM AS NUM
288{
a4caa1c0 289 $$ = cfg_alloc(sizeof(net_addr_roa6));
286e2011 290 net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
6aaaa635
OZ
291 if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
292 cf_error("Invalid max prefix length %u", $3);
513ad0a8
PT
293};
294
66acbc8d
OZ
295net_mpls_: MPLS NUM
296{
297 $$ = cfg_alloc(sizeof(net_addr_roa6));
298 net_fill_mpls($$, $2);
299}
300
04632fd7 301net_ip_: net_ip4_ | net_ip6_ ;
d311368b 302net_vpn_: net_vpn4_ | net_vpn6_ ;
62e64905 303net_roa_: net_roa4_ | net_roa6_ ;
513ad0a8 304
a4caa1c0
PT
305net_:
306 net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
d311368b 307 | net_vpn_
a4caa1c0 308 | net_roa_
77234bbb 309 | net_flow_
be17805c 310 | net_ip6_sadr_
66acbc8d 311 | net_mpls_
a4caa1c0 312 ;
d44e686e
OZ
313
314
04632fd7
OZ
315/* Networks - regular */
316
141fb51f
MM
317net_ip4:
318 net_ip4_
319 | CF_SYM_KNOWN {
320 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP4))
321 cf_error("IPv4 network constant expected");
322 $$ = * SYM_VAL($1).net;
323 }
324 ;
325
04632fd7
OZ
326net_ip6:
327 net_ip6_
9eef9c64 328 | CF_SYM_KNOWN {
04632fd7 329 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
9eef9c64 330 cf_error("IPv6 network constant expected");
04632fd7 331 $$ = * SYM_VAL($1).net;
d7661fbe 332 }
04632fd7
OZ
333 ;
334
335net_ip:
336 net_ip_
9eef9c64 337 | CF_SYM_KNOWN {
04632fd7 338 if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
9eef9c64 339 cf_error("IP network constant expected");
04632fd7 340 $$ = * SYM_VAL($1).net;
758458be
MM
341 }
342 ;
343
04632fd7
OZ
344net_any:
345 net_
9eef9c64 346 | CF_SYM_KNOWN {
04632fd7 347 if ($1->class != (SYM_CONSTANT | T_NET))
9eef9c64 348 cf_error("Network constant expected");
04632fd7
OZ
349 $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
350 }
351 ;
352
353net_or_ipa:
354 net_ip4_
355 | net_ip6_
356 | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
357 | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
9eef9c64 358 | CF_SYM_KNOWN {
04632fd7
OZ
359 if ($1->class == (SYM_CONSTANT | T_IP))
360 net_fill_ip_host(&($$), SYM_VAL($1).ip);
361 else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
362 $$ = * SYM_VAL($1).net;
363 else
9eef9c64 364 cf_error("IP address or network constant expected");
89d2355d 365 }
89d2355d
MM
366 ;
367
f2010f9c
JMM
368label_stack_start: NUM
369{
3c744164
JMM
370 $$ = cfg_allocz(sizeof(mpls_label_stack));
371 $$->len = 1;
372 $$->stack[0] = $1;
f2010f9c
JMM
373};
374
375label_stack:
376 label_stack_start
377 | label_stack '/' NUM {
3c744164 378 if ($1->len >= MPLS_MAX_LABEL_STACK)
62e64905 379 cf_error("Too many labels in stack");
3c744164 380 $1->stack[$1->len++] = $3;
f2010f9c
JMM
381 $$ = $1;
382 }
383;
04632fd7 384
f047271c 385time:
aee539f2 386 TEXT {
f047271c 387 $$ = tm_parse_time($1);
aee539f2 388 if (!$$)
f047271c 389 cf_error("Invalid date/time");
aee539f2 390 }
9d79fec8
PM
391 ;
392
9eceab33
OZ
393text:
394 TEXT
9eef9c64
MM
395 | CF_SYM_KNOWN {
396 if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String constant expected");
9eceab33
OZ
397 $$ = SYM_VAL($1).s;
398 }
399 ;
400
fe9f1a6d
OZ
401opttext:
402 TEXT
403 | /* empty */ { $$ = NULL; }
404 ;
405
116285f2
OZ
406text_or_ipa:
407 TEXT { $$.type = T_STRING; $$.val.s = $1; }
408 | IP4 { $$.type = T_IP; $$.val.ip = ipa_from_ip4($1); }
409 | IP6 { $$.type = T_IP; $$.val.ip = ipa_from_ip6($1); }
410 | CF_SYM_KNOWN {
411 if (($1->class == (SYM_CONSTANT | T_STRING)) ||
412 ($1->class == (SYM_CONSTANT | T_IP)))
413 $$ = *($1->val);
414 else
415 cf_error("String or IP constant expected");
416 }
417 | '(' term ')' {
418 $$ = cf_eval($2, T_VOID);
419 if (($$.type != T_BYTESTRING) && ($$.type != T_STRING))
420 cf_error("Bytestring or string value expected");
421 }
422 ;
423
f411a19b
OZ
424bytestring:
425 BYTETEXT
426 | bytestring_expr { $$ = cf_eval($1, T_BYTESTRING).val.bs; }
427 ;
428
429bytestring_text:
430 BYTETEXT { $$.type = T_BYTESTRING; $$.val.bs = $1; }
431 | TEXT { $$.type = T_STRING; $$.val.s = $1; }
432 | bytestring_expr {
433 $$ = cf_eval($1, T_VOID);
434 if (($$.type != T_BYTESTRING) && ($$.type != T_STRING))
435 cf_error("Bytestring or string value expected");
436 }
437 ;
438
439bytestring_expr:
440 symbol_value
441 | term_bs
442 | '(' term ')' { $$ = $2; }
443 ;
444
fe9f1a6d 445
f142750d
MM
446CF_CODE
447
448CF_END