]>
Commit | Line | Data |
---|---|---|
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 | ||
9 | CF_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 |
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 | ||
f142750d MM |
36 | CF_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 | 100 | CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN) |
0b62c3a7 | 101 | |
f142750d MM |
102 | CF_GRAMMAR |
103 | ||
0b62c3a7 MM |
104 | /* Basic config file structure */ |
105 | ||
bc2fb680 | 106 | config: conf_entries END { return 0; } |
ffb59d24 | 107 | | CLI_MARKER cli_cmd { return 0; } |
f142750d MM |
108 | ; |
109 | ||
110 | conf_entries: | |
111 | /* EMPTY */ | |
7f400d1c | 112 | | conf_entries conf |
f142750d MM |
113 | ; |
114 | ||
7f400d1c | 115 | CF_ADDTO(conf, ';') |
f142750d | 116 | |
1103b32e | 117 | |
72380a34 | 118 | /* Constant expressions */ |
0b62c3a7 | 119 | |
1103b32e OZ |
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 | ||
c9b66706 | 130 | expr: |
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 | 139 | expr_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 | ||
147 | bool: | |
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 | 159 | ipa: |
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 |
168 | ipa_scope: |
169 | /* empty */ { $$ = NULL; } | |
170 | | '%' SYM { $$ = if_get_by_name($2->name); } | |
171 | ; | |
172 | ||
d44e686e | 173 | |
04632fd7 | 174 | /* Networks - internal */ |
d44e686e | 175 | |
04632fd7 OZ |
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); | |
e691d16a | 183 | if ($$ == 255) cf_error("Invalid netmask %I4", $2); |
04632fd7 OZ |
184 | } |
185 | ; | |
d44e686e | 186 | |
04632fd7 OZ |
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 | }; | |
d44e686e | 193 | |
04632fd7 OZ |
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 | }; | |
d44e686e | 202 | |
d311368b MM |
203 | net_vpn4_: VPN_RD net_ip4_ |
204 | { | |
205 | $$ = cfg_alloc(sizeof(net_addr_vpn4)); | |
62e64905 | 206 | net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1); |
d311368b MM |
207 | } |
208 | ||
209 | net_vpn6_: VPN_RD net_ip6_ | |
210 | { | |
211 | $$ = cfg_alloc(sizeof(net_addr_vpn6)); | |
62e64905 | 212 | net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1); |
d311368b MM |
213 | } |
214 | ||
513ad0a8 PT |
215 | net_roa4_: net_ip4_ MAX NUM AS NUM |
216 | { | |
a4caa1c0 | 217 | $$ = cfg_alloc(sizeof(net_addr_roa4)); |
286e2011 | 218 | net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5); |
8860e991 | 219 | if ($3 < (int) net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH) |
513ad0a8 PT |
220 | cf_error("Invalid max prefix length %d", $3); |
221 | }; | |
222 | ||
223 | net_roa6_: net_ip6_ MAX NUM AS NUM | |
224 | { | |
a4caa1c0 | 225 | $$ = cfg_alloc(sizeof(net_addr_roa6)); |
286e2011 | 226 | net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5); |
8860e991 | 227 | if ($3 < (int) net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH) |
513ad0a8 PT |
228 | cf_error("Invalid max prefix length %d", $3); |
229 | }; | |
230 | ||
04632fd7 | 231 | net_ip_: net_ip4_ | net_ip6_ ; |
d311368b | 232 | net_vpn_: net_vpn4_ | net_vpn6_ ; |
62e64905 | 233 | net_roa_: net_roa4_ | net_roa6_ ; |
513ad0a8 | 234 | |
a4caa1c0 PT |
235 | net_: |
236 | net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } | |
d311368b | 237 | | net_vpn_ |
a4caa1c0 | 238 | | net_roa_ |
77234bbb | 239 | | net_flow_ |
a4caa1c0 | 240 | ; |
d44e686e OZ |
241 | |
242 | ||
04632fd7 OZ |
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; | |
d7661fbe | 251 | } |
04632fd7 OZ |
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; | |
758458be MM |
260 | } |
261 | ; | |
262 | ||
04632fd7 OZ |
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 | | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } | |
276 | | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } | |
277 | | SYM { | |
278 | if ($1->class == (SYM_CONSTANT | T_IP)) | |
279 | net_fill_ip_host(&($$), SYM_VAL($1).ip); | |
280 | else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) | |
281 | $$ = * SYM_VAL($1).net; | |
282 | else | |
283 | cf_error("IP address or network expected"); | |
89d2355d | 284 | } |
89d2355d MM |
285 | ; |
286 | ||
f2010f9c MM |
287 | label_stack_start: NUM |
288 | { | |
3c744164 MM |
289 | $$ = cfg_allocz(sizeof(mpls_label_stack)); |
290 | $$->len = 1; | |
291 | $$->stack[0] = $1; | |
f2010f9c MM |
292 | }; |
293 | ||
294 | label_stack: | |
295 | label_stack_start | |
296 | | label_stack '/' NUM { | |
3c744164 | 297 | if ($1->len >= MPLS_MAX_LABEL_STACK) |
62e64905 | 298 | cf_error("Too many labels in stack"); |
3c744164 | 299 | $1->stack[$1->len++] = $3; |
f2010f9c MM |
300 | $$ = $1; |
301 | } | |
302 | ; | |
04632fd7 | 303 | |
16c07e3d | 304 | datetime: |
aee539f2 | 305 | TEXT { |
0d3effcf | 306 | $$ = tm_parse_datetime($1); |
aee539f2 | 307 | if (!$$) |
0d3effcf | 308 | cf_error("Invalid date and time"); |
aee539f2 | 309 | } |
9d79fec8 PM |
310 | ; |
311 | ||
9eceab33 OZ |
312 | text: |
313 | TEXT | |
314 | | SYM { | |
315 | if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected"); | |
316 | $$ = SYM_VAL($1).s; | |
317 | } | |
318 | ; | |
319 | ||
fe9f1a6d OZ |
320 | opttext: |
321 | TEXT | |
322 | | /* empty */ { $$ = NULL; } | |
323 | ; | |
324 | ||
325 | ||
f142750d MM |
326 | CF_CODE |
327 | ||
328 | CF_END |