]> git.ipfire.org Git - thirdparty/bird.git/blob - conf/confbase.Y
Merge branch 'nexthop-merged' into int-new
[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 "sysdep/unix/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/cli.h"
23 #include "filter/filter.h"
24
25 /* FIXME: Turn on YYERROR_VERBOSE and work around lots of bison bugs? */
26
27 CF_DEFINES
28
29 static void
30 check_u16(unsigned val)
31 {
32 if (val > 0xFFFF)
33 cf_error("Value %d out of range (0-65535)", val);
34 }
35
36 CF_DECLS
37
38 %union {
39 int i;
40 u32 i32;
41 u64 i64;
42 ip_addr a;
43 ip4_addr ip4;
44 ip6_addr ip6;
45 net_addr net;
46 net_addr *net_ptr;
47 struct symbol *s;
48 char *t;
49 struct rtable_config *r;
50 struct channel_config *cc;
51 struct f_inst *x;
52 struct filter *f;
53 struct f_tree *e;
54 struct f_trie *trie;
55 struct f_val v;
56 struct f_path_mask *h;
57 struct password_item *p;
58 struct rt_show_data *ra;
59 struct sym_show_data *sd;
60 struct lsadb_show_data *ld;
61 struct iface *iface;
62 void *g;
63 bird_clock_t time;
64 struct f_prefix px;
65 struct proto_spec ps;
66 struct channel_limit cl;
67 struct timeformat *tf;
68 mpls_label_stack *mls;
69 }
70
71 %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
72 %token GEQ LEQ NEQ AND OR
73 %token PO PC
74 %token <i> NUM ENUM
75 %token <ip4> IP4
76 %token <ip6> IP6
77 %token <i64> VPN_RD
78 %token <s> SYM
79 %token <t> TEXT
80 %type <iface> ipa_scope
81
82 %type <i> expr bool pxlen4
83 %type <i32> expr_us
84 %type <time> datetime
85 %type <a> ipa
86 %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
87 %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
88 %type <mls> label_stack_start label_stack
89
90 %type <t> text opttext
91
92 %nonassoc PREFIX_DUMMY
93 %left AND OR
94 %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
95 %left '+' '-'
96 %left '*' '/' '%'
97 %left '!'
98 %nonassoc '.'
99
100 CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN)
101
102 CF_GRAMMAR
103
104 /* Basic config file structure */
105
106 config: conf_entries END { return 0; }
107 | CLI_MARKER cli_cmd { return 0; }
108 ;
109
110 conf_entries:
111 /* EMPTY */
112 | conf_entries conf
113 ;
114
115 CF_ADDTO(conf, ';')
116
117
118 /* Constant expressions */
119
120 CF_ADDTO(conf, definition)
121 definition:
122 DEFINE SYM '=' term ';' {
123 struct f_val *val = cfg_alloc(sizeof(struct f_val));
124 *val = f_eval($4, cfg_mem);
125 if (val->type == T_RETURN) cf_error("Runtime error");
126 cf_define_symbol($2, SYM_CONSTANT | val->type, val);
127 }
128 ;
129
130 expr:
131 NUM
132 | '(' term ')' { $$ = f_eval_int($2); }
133 | SYM {
134 if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected");
135 $$ = SYM_VAL($1).i; }
136 ;
137
138
139 expr_us:
140 expr S { $$ = (u32) $1 * 1000000; }
141 | expr MS { $$ = (u32) $1 * 1000; }
142 | expr US { $$ = (u32) $1 * 1; }
143 ;
144
145 /* Switches */
146
147 bool:
148 expr { $$ = !!$1; }
149 | ON { $$ = 1; }
150 | YES { $$ = 1; }
151 | OFF { $$ = 0; }
152 | NO { $$ = 0; }
153 | /* Silence means agreement */ { $$ = 1; }
154 ;
155
156
157 /* Addresses */
158
159 ipa:
160 IP4 { $$ = ipa_from_ip4($1); }
161 | IP6 { $$ = ipa_from_ip6($1); }
162 | SYM {
163 if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
164 $$ = SYM_VAL($1).ip;
165 }
166 ;
167
168 ipa_scope:
169 /* empty */ { $$ = NULL; }
170 | '%' SYM { $$ = if_get_by_name($2->name); }
171 ;
172
173
174 /* Networks - internal */
175
176 pxlen4:
177 '/' NUM {
178 if ($2 < 0 || $2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2);
179 $$ = $2;
180 }
181 | ':' IP4 {
182 $$ = ip4_masklen($2);
183 if ($$ == 255) cf_error("Invalid netmask %I4", $2);
184 }
185 ;
186
187 net_ip4_: IP4 pxlen4
188 {
189 net_fill_ip4(&($$), $1, $2);
190 if (!net_validate_ip4((net_addr_ip4 *) &($$)))
191 cf_error("Invalid IPv4 prefix");
192 };
193
194 net_ip6_: IP6 '/' NUM
195 {
196 net_fill_ip6(&($$), $1, $3);
197 if ($3 < 0 || $3 > IP6_MAX_PREFIX_LENGTH)
198 cf_error("Invalid prefix length %d", $3);
199 if (!net_validate_ip6((net_addr_ip6 *) &($$)))
200 cf_error("Invalid IPv6 prefix");
201 };
202
203 net_vpn4_: VPN_RD net_ip4_
204 {
205 $$ = cfg_alloc(sizeof(net_addr_vpn4));
206 net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
207 }
208
209 net_vpn6_: VPN_RD net_ip6_
210 {
211 $$ = cfg_alloc(sizeof(net_addr_vpn6));
212 net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
213 }
214
215 net_roa4_: net_ip4_ MAX NUM AS NUM
216 {
217 $$ = cfg_alloc(sizeof(net_addr_roa4));
218 net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
219 if ($3 < (int) net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
220 cf_error("Invalid max prefix length %d", $3);
221 };
222
223 net_roa6_: net_ip6_ MAX NUM AS NUM
224 {
225 $$ = cfg_alloc(sizeof(net_addr_roa6));
226 net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
227 if ($3 < (int) net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
228 cf_error("Invalid max prefix length %d", $3);
229 };
230
231 net_ip_: net_ip4_ | net_ip6_ ;
232 net_vpn_: net_vpn4_ | net_vpn6_ ;
233 net_roa_: net_roa4_ | net_roa6_ ;
234
235 net_:
236 net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
237 | net_vpn_
238 | net_roa_
239 | net_flow_
240 ;
241
242
243 /* Networks - regular */
244
245 net_ip6:
246 net_ip6_
247 | SYM {
248 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
249 cf_error("IPv6 network expected");
250 $$ = * SYM_VAL($1).net;
251 }
252 ;
253
254 net_ip:
255 net_ip_
256 | SYM {
257 if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
258 cf_error("IP network expected");
259 $$ = * SYM_VAL($1).net;
260 }
261 ;
262
263 net_any:
264 net_
265 | SYM {
266 if ($1->class != (SYM_CONSTANT | T_NET))
267 cf_error("Network expected");
268 $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
269 }
270 ;
271
272 net_or_ipa:
273 net_ip4_
274 | net_ip6_
275 | net_vpn4_ { $$ = *$1; }
276 | net_vpn6_ { $$ = *$1; }
277 | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
278 | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
279 | SYM {
280 if ($1->class == (SYM_CONSTANT | T_IP))
281 net_fill_ip_host(&($$), SYM_VAL($1).ip);
282 else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
283 $$ = * SYM_VAL($1).net;
284 else
285 cf_error("IP address or network expected");
286 }
287 ;
288
289 label_stack_start: NUM
290 {
291 $$ = cfg_allocz(sizeof(mpls_label_stack));
292 $$->len = 1;
293 $$->stack[0] = $1;
294 };
295
296 label_stack:
297 label_stack_start
298 | label_stack '/' NUM {
299 if ($1->len >= MPLS_MAX_LABEL_STACK)
300 cf_error("Too many labels in stack");
301 $1->stack[$1->len++] = $3;
302 $$ = $1;
303 }
304 ;
305
306 datetime:
307 TEXT {
308 $$ = tm_parse_datetime($1);
309 if (!$$)
310 cf_error("Invalid date and time");
311 }
312 ;
313
314 text:
315 TEXT
316 | SYM {
317 if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected");
318 $$ = SYM_VAL($1).s;
319 }
320 ;
321
322 opttext:
323 TEXT
324 | /* empty */ { $$ = NULL; }
325 ;
326
327
328 CF_CODE
329
330 CF_END