]>
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; |
f142750d | 41 | ip_addr a; |
fe9f1a6d OZ |
42 | ip4_addr ip4; |
43 | ip6_addr ip6; | |
04632fd7 | 44 | net_addr net; |
d44e686e | 45 | net_addr *net_ptr; |
f142750d MM |
46 | struct symbol *s; |
47 | char *t; | |
0e02abfd | 48 | struct rtable_config *r; |
f4a60a9b | 49 | struct channel_config *cc; |
e0f2e42f MM |
50 | struct f_inst *x; |
51 | struct filter *f; | |
38506f71 | 52 | struct f_tree *e; |
b1a597e0 | 53 | struct f_trie *trie; |
38506f71 | 54 | struct f_val v; |
dcab7890 | 55 | struct f_path_mask *h; |
9d79fec8 | 56 | struct password_item *p; |
730f2e2c | 57 | struct rt_show_data *ra; |
0f808c06 | 58 | struct sym_show_data *sd; |
20ab192b | 59 | struct lsadb_show_data *ld; |
69a8259c | 60 | struct iface *iface; |
4ab5331c | 61 | void *g; |
aee539f2 | 62 | bird_clock_t time; |
5e173e9f | 63 | struct f_prefix px; |
e304fd4b | 64 | struct proto_spec ps; |
f4a60a9b | 65 | struct channel_limit cl; |
c37e7851 | 66 | struct timeformat *tf; |
f142750d MM |
67 | } |
68 | ||
b8cc390e | 69 | %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT |
5f4aee76 | 70 | %token GEQ LEQ NEQ AND OR |
cf186034 | 71 | %token PO PC |
944f008a | 72 | %token <i> NUM ENUM |
fe9f1a6d OZ |
73 | %token <ip4> IP4 |
74 | %token <ip6> IP6 | |
f142750d MM |
75 | %token <s> SYM |
76 | %token <t> TEXT | |
69a8259c | 77 | %type <iface> ipa_scope |
f142750d | 78 | |
04632fd7 | 79 | %type <i> expr bool pxlen4 |
6a8d3f1c | 80 | %type <i32> expr_us |
aee539f2 | 81 | %type <time> datetime |
04632fd7 | 82 | %type <a> ipa |
a4caa1c0 PT |
83 | %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa |
84 | %type <net_ptr> net_ net_any net_roa4_ net_roa6_ net_roa_ | |
d44e686e OZ |
85 | |
86 | %type <t> text opttext | |
0b62c3a7 | 87 | |
60de3356 | 88 | %nonassoc PREFIX_DUMMY |
1960d203 | 89 | %left AND OR |
768d5e10 | 90 | %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC |
1960d203 | 91 | %left '+' '-' |
0b62c3a7 | 92 | %left '*' '/' '%' |
23b1539b | 93 | %left '!' |
112d71a7 | 94 | %nonassoc '.' |
0b62c3a7 | 95 | |
dcde7ae5 | 96 | CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT) |
0b62c3a7 | 97 | |
f142750d MM |
98 | CF_GRAMMAR |
99 | ||
0b62c3a7 MM |
100 | /* Basic config file structure */ |
101 | ||
bc2fb680 | 102 | config: conf_entries END { return 0; } |
ffb59d24 | 103 | | CLI_MARKER cli_cmd { return 0; } |
f142750d MM |
104 | ; |
105 | ||
106 | conf_entries: | |
107 | /* EMPTY */ | |
7f400d1c | 108 | | conf_entries conf |
f142750d MM |
109 | ; |
110 | ||
7f400d1c | 111 | CF_ADDTO(conf, ';') |
f142750d | 112 | |
1103b32e | 113 | |
72380a34 | 114 | /* Constant expressions */ |
0b62c3a7 | 115 | |
1103b32e OZ |
116 | CF_ADDTO(conf, definition) |
117 | definition: | |
118 | DEFINE SYM '=' term ';' { | |
119 | struct f_val *val = cfg_alloc(sizeof(struct f_val)); | |
120 | *val = f_eval($4, cfg_mem); | |
121 | if (val->type == T_RETURN) cf_error("Runtime error"); | |
122 | cf_define_symbol($2, SYM_CONSTANT | val->type, val); | |
123 | } | |
124 | ; | |
125 | ||
c9b66706 | 126 | expr: |
0b62c3a7 | 127 | NUM |
cc590a11 | 128 | | '(' term ')' { $$ = f_eval_int($2); } |
1103b32e OZ |
129 | | SYM { |
130 | if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected"); | |
131 | $$ = SYM_VAL($1).i; } | |
0b62c3a7 MM |
132 | ; |
133 | ||
6a8d3f1c | 134 | |
6a8d3f1c | 135 | expr_us: |
0e175f9f OZ |
136 | expr S { $$ = (u32) $1 * 1000000; } |
137 | | expr MS { $$ = (u32) $1 * 1000; } | |
138 | | expr US { $$ = (u32) $1 * 1; } | |
6a8d3f1c OZ |
139 | ; |
140 | ||
b8cc390e OZ |
141 | /* expr_u16: expr { check_u16($1); $$ = $1; }; */ |
142 | ||
166b9c49 MM |
143 | /* Switches */ |
144 | ||
145 | bool: | |
c9b66706 | 146 | expr {$$ = !!$1; } |
166b9c49 MM |
147 | | ON { $$ = 1; } |
148 | | YES { $$ = 1; } | |
149 | | OFF { $$ = 0; } | |
150 | | NO { $$ = 0; } | |
151 | | /* Silence means agreement */ { $$ = 1; } | |
152 | ; | |
153 | ||
e3f2d5fc | 154 | |
04632fd7 | 155 | /* Addresses */ |
fe9f1a6d | 156 | |
e3f2d5fc | 157 | ipa: |
04632fd7 OZ |
158 | IP4 { $$ = ipa_from_ip4($1); } |
159 | | IP6 { $$ = ipa_from_ip6($1); } | |
e3f2d5fc | 160 | | SYM { |
1103b32e | 161 | if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); |
5e173e9f | 162 | $$ = SYM_VAL($1).ip; |
e3f2d5fc MM |
163 | } |
164 | ; | |
89d2355d | 165 | |
69a8259c OZ |
166 | ipa_scope: |
167 | /* empty */ { $$ = NULL; } | |
168 | | '%' SYM { $$ = if_get_by_name($2->name); } | |
169 | ; | |
170 | ||
d44e686e | 171 | |
04632fd7 | 172 | /* Networks - internal */ |
d44e686e | 173 | |
04632fd7 OZ |
174 | pxlen4: |
175 | '/' NUM { | |
176 | if ($2 < 0 || $2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); | |
177 | $$ = $2; | |
178 | } | |
179 | | ':' IP4 { | |
180 | $$ = ip4_masklen($2); | |
e691d16a | 181 | if ($$ == 255) cf_error("Invalid netmask %I4", $2); |
04632fd7 OZ |
182 | } |
183 | ; | |
d44e686e | 184 | |
04632fd7 OZ |
185 | net_ip4_: IP4 pxlen4 |
186 | { | |
187 | net_fill_ip4(&($$), $1, $2); | |
188 | if (!net_validate_ip4((net_addr_ip4 *) &($$))) | |
189 | cf_error("Invalid IPv4 prefix"); | |
190 | }; | |
d44e686e | 191 | |
04632fd7 OZ |
192 | net_ip6_: IP6 '/' NUM |
193 | { | |
194 | net_fill_ip6(&($$), $1, $3); | |
195 | if ($3 < 0 || $3 > IP6_MAX_PREFIX_LENGTH) | |
196 | cf_error("Invalid prefix length %d", $3); | |
197 | if (!net_validate_ip6((net_addr_ip6 *) &($$))) | |
198 | cf_error("Invalid IPv6 prefix"); | |
199 | }; | |
d44e686e | 200 | |
513ad0a8 PT |
201 | net_roa4_: net_ip4_ MAX NUM AS NUM |
202 | { | |
a4caa1c0 | 203 | $$ = cfg_alloc(sizeof(net_addr_roa4)); |
286e2011 OZ |
204 | net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5); |
205 | if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH) | |
513ad0a8 PT |
206 | cf_error("Invalid max prefix length %d", $3); |
207 | }; | |
208 | ||
209 | net_roa6_: net_ip6_ MAX NUM AS NUM | |
210 | { | |
a4caa1c0 | 211 | $$ = cfg_alloc(sizeof(net_addr_roa6)); |
286e2011 OZ |
212 | net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5); |
213 | if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH) | |
513ad0a8 PT |
214 | cf_error("Invalid max prefix length %d", $3); |
215 | }; | |
216 | ||
04632fd7 | 217 | net_ip_: net_ip4_ | net_ip6_ ; |
513ad0a8 PT |
218 | net_roa_: net_roa4_ | net_roa6_ ; |
219 | ||
a4caa1c0 PT |
220 | net_: |
221 | net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } | |
222 | | net_roa_ | |
223 | ; | |
d44e686e OZ |
224 | |
225 | ||
04632fd7 OZ |
226 | /* Networks - regular */ |
227 | ||
228 | net_ip6: | |
229 | net_ip6_ | |
230 | | SYM { | |
231 | if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6)) | |
232 | cf_error("IPv6 network expected"); | |
233 | $$ = * SYM_VAL($1).net; | |
d7661fbe | 234 | } |
04632fd7 OZ |
235 | ; |
236 | ||
237 | net_ip: | |
238 | net_ip_ | |
239 | | SYM { | |
240 | if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net)) | |
241 | cf_error("IP network expected"); | |
242 | $$ = * SYM_VAL($1).net; | |
758458be MM |
243 | } |
244 | ; | |
245 | ||
04632fd7 OZ |
246 | net_any: |
247 | net_ | |
248 | | SYM { | |
249 | if ($1->class != (SYM_CONSTANT | T_NET)) | |
250 | cf_error("Network expected"); | |
251 | $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ | |
252 | } | |
253 | ; | |
254 | ||
255 | net_or_ipa: | |
256 | net_ip4_ | |
257 | | net_ip6_ | |
258 | | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } | |
259 | | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } | |
260 | | SYM { | |
261 | if ($1->class == (SYM_CONSTANT | T_IP)) | |
262 | net_fill_ip_host(&($$), SYM_VAL($1).ip); | |
263 | else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) | |
264 | $$ = * SYM_VAL($1).net; | |
265 | else | |
266 | cf_error("IP address or network expected"); | |
89d2355d | 267 | } |
89d2355d MM |
268 | ; |
269 | ||
04632fd7 | 270 | |
16c07e3d | 271 | datetime: |
aee539f2 | 272 | TEXT { |
0d3effcf | 273 | $$ = tm_parse_datetime($1); |
aee539f2 | 274 | if (!$$) |
0d3effcf | 275 | cf_error("Invalid date and time"); |
aee539f2 | 276 | } |
9d79fec8 PM |
277 | ; |
278 | ||
9eceab33 OZ |
279 | text: |
280 | TEXT | |
281 | | SYM { | |
282 | if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected"); | |
283 | $$ = SYM_VAL($1).s; | |
284 | } | |
285 | ; | |
286 | ||
fe9f1a6d OZ |
287 | opttext: |
288 | TEXT | |
289 | | /* empty */ { $$ = NULL; } | |
290 | ; | |
291 | ||
292 | ||
f142750d MM |
293 | CF_CODE |
294 | ||
295 | CF_END |