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