]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/confbase.Y
Add a hint for an invalid IP prefix
[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"
7152e5ef 17#include "sysdep/unix/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
30check_u16(unsigned val)
31{
32 if (val > 0xFFFF)
33 cf_error("Value %d out of range (0-65535)", val);
34}
35
f142750d
MM
36CF_DECLS
37
38%union {
39 int i;
dce26783 40 u32 i32;
d311368b 41 u64 i64;
f142750d 42 ip_addr a;
fe9f1a6d
OZ
43 ip4_addr ip4;
44 ip6_addr ip6;
04632fd7 45 net_addr net;
d44e686e 46 net_addr *net_ptr;
f142750d
MM
47 struct symbol *s;
48 char *t;
0e02abfd 49 struct rtable_config *r;
f4a60a9b 50 struct channel_config *cc;
e0f2e42f
MM
51 struct f_inst *x;
52 struct filter *f;
38506f71 53 struct f_tree *e;
b1a597e0 54 struct f_trie *trie;
38506f71 55 struct f_val v;
dcab7890 56 struct f_path_mask *h;
9d79fec8 57 struct password_item *p;
730f2e2c 58 struct rt_show_data *ra;
0f808c06 59 struct sym_show_data *sd;
20ab192b 60 struct lsadb_show_data *ld;
69a8259c 61 struct iface *iface;
4ab5331c 62 void *g;
aee539f2 63 bird_clock_t time;
5e173e9f 64 struct f_prefix px;
e304fd4b 65 struct proto_spec ps;
f4a60a9b 66 struct channel_limit cl;
c37e7851 67 struct timeformat *tf;
3c744164 68 mpls_label_stack *mls;
f142750d
MM
69}
70
b8cc390e 71%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
5f4aee76 72%token GEQ LEQ NEQ AND OR
cf186034 73%token PO PC
944f008a 74%token <i> NUM ENUM
fe9f1a6d
OZ
75%token <ip4> IP4
76%token <ip6> IP6
d311368b 77%token <i64> VPN_RD
f142750d
MM
78%token <s> SYM
79%token <t> TEXT
69a8259c 80%type <iface> ipa_scope
f142750d 81
04632fd7 82%type <i> expr bool pxlen4
6a8d3f1c 83%type <i32> expr_us
aee539f2 84%type <time> datetime
04632fd7 85%type <a> ipa
a4caa1c0 86%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
d311368b 87%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
3c744164 88%type <mls> label_stack_start label_stack
d44e686e
OZ
89
90%type <t> text opttext
0b62c3a7 91
60de3356 92%nonassoc PREFIX_DUMMY
1960d203 93%left AND OR
768d5e10 94%nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
1960d203 95%left '+' '-'
0b62c3a7 96%left '*' '/' '%'
23b1539b 97%left '!'
112d71a7 98%nonassoc '.'
0b62c3a7 99
d311368b 100CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN)
0b62c3a7 101
f142750d
MM
102CF_GRAMMAR
103
0b62c3a7
MM
104/* Basic config file structure */
105
bc2fb680 106config: conf_entries END { return 0; }
ffb59d24 107 | CLI_MARKER cli_cmd { return 0; }
f142750d
MM
108 ;
109
110conf_entries:
111 /* EMPTY */
7f400d1c 112 | conf_entries conf
f142750d
MM
113 ;
114
7f400d1c 115CF_ADDTO(conf, ';')
f142750d 116
1103b32e 117
72380a34 118/* Constant expressions */
0b62c3a7 119
1103b32e
OZ
120CF_ADDTO(conf, definition)
121definition:
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
c9b66706 130expr:
0b62c3a7 131 NUM
cc590a11 132 | '(' term ')' { $$ = f_eval_int($2); }
1103b32e
OZ
133 | SYM {
134 if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected");
135 $$ = SYM_VAL($1).i; }
0b62c3a7
MM
136 ;
137
6a8d3f1c 138
6a8d3f1c 139expr_us:
0e175f9f
OZ
140 expr S { $$ = (u32) $1 * 1000000; }
141 | expr MS { $$ = (u32) $1 * 1000; }
142 | expr US { $$ = (u32) $1 * 1; }
6a8d3f1c
OZ
143 ;
144
166b9c49
MM
145/* Switches */
146
147bool:
c8cafc8e 148 expr { $$ = !!$1; }
166b9c49
MM
149 | ON { $$ = 1; }
150 | YES { $$ = 1; }
151 | OFF { $$ = 0; }
152 | NO { $$ = 0; }
153 | /* Silence means agreement */ { $$ = 1; }
154 ;
155
e3f2d5fc 156
04632fd7 157/* Addresses */
fe9f1a6d 158
e3f2d5fc 159ipa:
04632fd7
OZ
160 IP4 { $$ = ipa_from_ip4($1); }
161 | IP6 { $$ = ipa_from_ip6($1); }
e3f2d5fc 162 | SYM {
1103b32e 163 if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
5e173e9f 164 $$ = SYM_VAL($1).ip;
e3f2d5fc
MM
165 }
166 ;
89d2355d 167
69a8259c
OZ
168ipa_scope:
169 /* empty */ { $$ = NULL; }
170 | '%' SYM { $$ = if_get_by_name($2->name); }
171 ;
172
d44e686e 173
04632fd7 174/* Networks - internal */
d44e686e 175
04632fd7
OZ
176pxlen4:
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);
e691d16a 183 if ($$ == 255) cf_error("Invalid netmask %I4", $2);
04632fd7
OZ
184 }
185 ;
d44e686e 186
04632fd7
OZ
187net_ip4_: IP4 pxlen4
188{
189 net_fill_ip4(&($$), $1, $2);
0705a1c5
PT
190
191 net_addr_ip4 *n = (void *) &($$);
192 if (!net_validate_ip4(n))
193 cf_error("Invalid IPv4 prefix %I4/%d, maybe you wanted %I4/%d",
194 n->prefix, n->pxlen, ip4_and(n->prefix, ip4_mkmask(n->pxlen)), n->pxlen);
04632fd7 195};
d44e686e 196
04632fd7
OZ
197net_ip6_: IP6 '/' NUM
198{
04632fd7
OZ
199 if ($3 < 0 || $3 > IP6_MAX_PREFIX_LENGTH)
200 cf_error("Invalid prefix length %d", $3);
0705a1c5
PT
201
202 net_fill_ip6(&($$), $1, $3);
203
204 net_addr_ip6 *n = (void *) &($$);
205 if (!net_validate_ip6(n))
206 cf_error("Invalid IPv6 prefix %I6/%d, maybe you wanted %I6/%d",
207 n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
04632fd7 208};
d44e686e 209
d311368b
JMM
210net_vpn4_: VPN_RD net_ip4_
211{
212 $$ = cfg_alloc(sizeof(net_addr_vpn4));
62e64905 213 net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
d311368b
JMM
214}
215
216net_vpn6_: VPN_RD net_ip6_
217{
218 $$ = cfg_alloc(sizeof(net_addr_vpn6));
62e64905 219 net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
d311368b
JMM
220}
221
513ad0a8
PT
222net_roa4_: net_ip4_ MAX NUM AS NUM
223{
a4caa1c0 224 $$ = cfg_alloc(sizeof(net_addr_roa4));
286e2011 225 net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
8860e991 226 if ($3 < (int) net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
513ad0a8
PT
227 cf_error("Invalid max prefix length %d", $3);
228};
229
230net_roa6_: net_ip6_ MAX NUM AS NUM
231{
a4caa1c0 232 $$ = cfg_alloc(sizeof(net_addr_roa6));
286e2011 233 net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
8860e991 234 if ($3 < (int) net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
513ad0a8
PT
235 cf_error("Invalid max prefix length %d", $3);
236};
237
04632fd7 238net_ip_: net_ip4_ | net_ip6_ ;
d311368b 239net_vpn_: net_vpn4_ | net_vpn6_ ;
62e64905 240net_roa_: net_roa4_ | net_roa6_ ;
513ad0a8 241
a4caa1c0
PT
242net_:
243 net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
d311368b 244 | net_vpn_
a4caa1c0 245 | net_roa_
77234bbb 246 | net_flow_
a4caa1c0 247 ;
d44e686e
OZ
248
249
04632fd7
OZ
250/* Networks - regular */
251
252net_ip6:
253 net_ip6_
254 | SYM {
255 if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
256 cf_error("IPv6 network expected");
257 $$ = * SYM_VAL($1).net;
d7661fbe 258 }
04632fd7
OZ
259 ;
260
261net_ip:
262 net_ip_
263 | SYM {
264 if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
265 cf_error("IP network expected");
266 $$ = * SYM_VAL($1).net;
758458be
MM
267 }
268 ;
269
04632fd7
OZ
270net_any:
271 net_
272 | SYM {
273 if ($1->class != (SYM_CONSTANT | T_NET))
274 cf_error("Network expected");
275 $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
276 }
277 ;
278
279net_or_ipa:
280 net_ip4_
281 | net_ip6_
282 | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
283 | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
284 | SYM {
285 if ($1->class == (SYM_CONSTANT | T_IP))
286 net_fill_ip_host(&($$), SYM_VAL($1).ip);
287 else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
288 $$ = * SYM_VAL($1).net;
289 else
290 cf_error("IP address or network expected");
89d2355d 291 }
89d2355d
MM
292 ;
293
f2010f9c
JMM
294label_stack_start: NUM
295{
3c744164
JMM
296 $$ = cfg_allocz(sizeof(mpls_label_stack));
297 $$->len = 1;
298 $$->stack[0] = $1;
f2010f9c
JMM
299};
300
301label_stack:
302 label_stack_start
303 | label_stack '/' NUM {
3c744164 304 if ($1->len >= MPLS_MAX_LABEL_STACK)
62e64905 305 cf_error("Too many labels in stack");
3c744164 306 $1->stack[$1->len++] = $3;
f2010f9c
JMM
307 $$ = $1;
308 }
309;
04632fd7 310
16c07e3d 311datetime:
aee539f2 312 TEXT {
0d3effcf 313 $$ = tm_parse_datetime($1);
aee539f2 314 if (!$$)
0d3effcf 315 cf_error("Invalid date and time");
aee539f2 316 }
9d79fec8
PM
317 ;
318
9eceab33
OZ
319text:
320 TEXT
321 | SYM {
322 if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected");
323 $$ = SYM_VAL($1).s;
324 }
325 ;
326
fe9f1a6d
OZ
327opttext:
328 TEXT
329 | /* empty */ { $$ = NULL; }
330 ;
331
332
f142750d
MM
333CF_CODE
334
335CF_END