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