]> git.ipfire.org Git - thirdparty/bird.git/blob - proto/radv/config.Y
Filter refactoring: dropped the recursion from the interpreter
[thirdparty/bird.git] / proto / radv / config.Y
1 /*
2 * BIRD -- Router Advertisement Configuration
3 *
4 *
5 * Can be freely distributed and used under the terms of the GNU GPL.
6 */
7
8 CF_HDR
9
10 #include "proto/radv/radv.h"
11
12 CF_DEFINES
13
14 #define RADV_CFG ((struct radv_config *) this_proto)
15 #define RADV_IFACE ((struct radv_iface_config *) this_ipatt)
16 #define RADV_PREFIX this_radv_prefix
17 #define RADV_RDNSS (&this_radv_rdnss)
18 #define RADV_DNSSL (&this_radv_dnssl)
19
20 static struct radv_prefix_config *this_radv_prefix;
21 static struct radv_rdnss_config this_radv_rdnss;
22 static struct radv_dnssl_config this_radv_dnssl;
23 static list radv_dns_list; /* Used by radv_rdnss and radv_dnssl */
24 static u8 radv_mult_val; /* Used by radv_mult for second return value */
25
26
27 CF_DECLS
28
29 CF_KEYWORDS(RADV, PREFIX, INTERFACE, MIN, MAX, RA, DELAY, INTERVAL,
30 MANAGED, OTHER, CONFIG, LINGER, LINK, MTU, REACHABLE, TIME, RETRANS,
31 TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
32 LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
33 LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH, PROPAGATE,
34 ROUTE, ROUTES, RA_PREFERENCE, RA_LIFETIME)
35
36 CF_ENUM(T_ENUM_RA_PREFERENCE, RA_PREF_, LOW, MEDIUM, HIGH)
37
38 %type<i> radv_mult radv_sensitive radv_preference
39
40 CF_GRAMMAR
41
42 proto: radv_proto ;
43
44 radv_proto_start: proto_start RADV
45 {
46 this_proto = proto_config_new(&proto_radv, $1);
47
48 init_list(&RADV_CFG->patt_list);
49 init_list(&RADV_CFG->pref_list);
50 init_list(&RADV_CFG->rdnss_list);
51 init_list(&RADV_CFG->dnssl_list);
52 };
53
54 radv_proto_item:
55 proto_item
56 | proto_channel
57 | INTERFACE radv_iface
58 | PREFIX radv_prefix { add_tail(&RADV_CFG->pref_list, NODE this_radv_prefix); }
59 | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_CFG->rdnss_list, &radv_dns_list); }
60 | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_CFG->dnssl_list, &radv_dns_list); }
61 | TRIGGER net_ip6 { RADV_CFG->trigger = $2; }
62 | PROPAGATE ROUTES bool { RADV_CFG->propagate_routes = $3; }
63 ;
64
65 radv_proto_opts:
66 /* empty */
67 | radv_proto_opts radv_proto_item ';'
68 ;
69
70 radv_proto:
71 radv_proto_start proto_name '{' radv_proto_opts '}';
72
73
74 radv_iface_start:
75 {
76 this_ipatt = cfg_allocz(sizeof(struct radv_iface_config));
77 add_tail(&RADV_CFG->patt_list, NODE this_ipatt);
78 init_list(&this_ipatt->ipn_list);
79 init_list(&RADV_IFACE->pref_list);
80 init_list(&RADV_IFACE->rdnss_list);
81 init_list(&RADV_IFACE->dnssl_list);
82
83 RADV_IFACE->min_ra_int = (u32) -1; /* undefined */
84 RADV_IFACE->max_ra_int = DEFAULT_MAX_RA_INT;
85 RADV_IFACE->min_delay = DEFAULT_MIN_DELAY;
86 RADV_IFACE->prefix_linger_time = (u32) -1;
87 RADV_IFACE->route_linger_time = (u32) -1;
88 RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
89 RADV_IFACE->default_lifetime = (u32) -1;
90 RADV_IFACE->default_lifetime_sensitive = 1;
91 RADV_IFACE->default_preference = RA_PREF_MEDIUM;
92 RADV_IFACE->route_lifetime = (u32) -1;
93 RADV_IFACE->route_lifetime_sensitive = 0;
94 RADV_IFACE->route_preference = RA_PREF_MEDIUM;
95 };
96
97 radv_iface_item:
98 MIN RA INTERVAL expr { RADV_IFACE->min_ra_int = $4; if ($4 < 3) cf_error("Min RA interval must be at least 3"); }
99 | MAX RA INTERVAL expr { RADV_IFACE->max_ra_int = $4; if (($4 < 4) || ($4 > 1800)) cf_error("Max RA interval must be in range 4-1800"); }
100 | MIN DELAY expr { RADV_IFACE->min_delay = $3; if ($3 <= 0) cf_error("Min delay must be positive"); }
101 | MANAGED bool { RADV_IFACE->managed = $2; }
102 | OTHER CONFIG bool { RADV_IFACE->other_config = $3; }
103 | LINK MTU expr { RADV_IFACE->link_mtu = $3; }
104 | REACHABLE TIME expr { RADV_IFACE->reachable_time = $3; if ($3 > 3600000) cf_error("Reachable time must be in range 0-3600000"); }
105 | RETRANS TIMER expr { RADV_IFACE->retrans_timer = $3; }
106 | CURRENT HOP LIMIT expr { RADV_IFACE->current_hop_limit = $4; if ($4 > 255) cf_error("Current hop limit must be in range 0-255"); }
107 | DEFAULT LIFETIME expr radv_sensitive {
108 RADV_IFACE->default_lifetime = $3;
109 if ($3 > 9000) cf_error("Default lifetime must be in range 0-9000");
110 if ($4 != (uint) -1) RADV_IFACE->default_lifetime_sensitive = $4;
111 }
112 | ROUTE LIFETIME expr radv_sensitive {
113 RADV_IFACE->route_lifetime = $3;
114 if ($4 != (uint) -1) RADV_IFACE->route_lifetime_sensitive = $4;
115 }
116 | DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; }
117 | ROUTE PREFERENCE radv_preference { RADV_IFACE->route_preference = $3; }
118 | PREFIX LINGER TIME expr { RADV_IFACE->prefix_linger_time = $4; }
119 | ROUTE LINGER TIME expr { RADV_IFACE->route_linger_time = $4; }
120 | PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
121 | RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
122 | DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
123 | RDNSS LOCAL bool { RADV_IFACE->rdnss_local = $3; }
124 | DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
125 ;
126
127 radv_preference:
128 LOW { $$ = RA_PREF_LOW; }
129 | MEDIUM { $$ = RA_PREF_MEDIUM; }
130 | HIGH { $$ = RA_PREF_HIGH; }
131
132 radv_iface_finish:
133 {
134 struct radv_iface_config *ic = RADV_IFACE;
135
136 if (ic->min_ra_int == (u32) -1)
137 ic->min_ra_int = MAX_(ic->max_ra_int / 3, 3);
138
139 if (ic->default_lifetime == (u32) -1)
140 ic->default_lifetime = 3 * ic->max_ra_int;
141
142 if (ic->route_lifetime == (u32) -1)
143 ic->route_lifetime = 3 * ic->max_ra_int;
144
145 if (ic->prefix_linger_time == (u32) -1)
146 ic->prefix_linger_time = 3 * ic->max_ra_int;
147
148 if (ic->route_linger_time == (u32) -1)
149 ic->route_linger_time = 3 * ic->max_ra_int;
150
151 if ((ic->min_ra_int > 3) &&
152 (ic->min_ra_int > (ic->max_ra_int * 3 / 4)))
153 cf_error("Min RA interval must be at most 3/4 * Max RA interval");
154
155 if ((ic->default_lifetime > 0) && (ic->default_lifetime < ic->max_ra_int))
156 cf_error("Default lifetime must be either 0 or at least Max RA interval");
157
158 if ((ic->route_lifetime > 0) && (ic->route_lifetime < ic->max_ra_int))
159 cf_error("Route lifetime must be either 0 or at least Max RA interval");
160
161 if ((ic->prefix_linger_time > 0) && (ic->prefix_linger_time < ic->max_ra_int))
162 cf_error("Prefix linger time must be either 0 or at least Max RA interval");
163
164 if ((ic->route_linger_time > 0) && (ic->route_linger_time < ic->max_ra_int))
165 cf_error("Route linger time must be either 0 or at least Max RA interval");
166
167 RADV_CFG->max_linger_time = MAX_(RADV_CFG->max_linger_time, ic->route_linger_time);
168 };
169
170
171 radv_iface_opts:
172 /* empty */
173 | radv_iface_opts radv_iface_item ';'
174 ;
175
176 radv_iface_opt_list:
177 /* empty */
178 | '{' radv_iface_opts '}'
179 ;
180
181 radv_iface:
182 radv_iface_start iface_patt_list_nopx radv_iface_opt_list radv_iface_finish;
183
184
185 radv_prefix_start: net_ip6
186 {
187 this_radv_prefix = cfg_allocz(sizeof(struct radv_prefix_config));
188 RADV_PREFIX->prefix = *(net_addr_ip6 *) &($1);
189
190 RADV_PREFIX->onlink = 1;
191 RADV_PREFIX->autonomous = 1;
192 RADV_PREFIX->valid_lifetime = DEFAULT_VALID_LIFETIME;
193 RADV_PREFIX->preferred_lifetime = DEFAULT_PREFERRED_LIFETIME;
194 };
195
196 radv_prefix_item:
197 SKIP bool { RADV_PREFIX->skip = $2; }
198 | ONLINK bool { RADV_PREFIX->onlink = $2; }
199 | AUTONOMOUS bool { RADV_PREFIX->autonomous = $2; }
200 | VALID LIFETIME expr radv_sensitive {
201 RADV_PREFIX->valid_lifetime = $3;
202 if ($4 != (uint) -1) RADV_PREFIX->valid_lifetime_sensitive = $4;
203 }
204 | PREFERRED LIFETIME expr radv_sensitive {
205 RADV_PREFIX->preferred_lifetime = $3;
206 if ($4 != (uint) -1) RADV_PREFIX->preferred_lifetime_sensitive = $4;
207 }
208 ;
209
210 radv_prefix_finish:
211 {
212 if (RADV_PREFIX->preferred_lifetime > RADV_PREFIX->valid_lifetime)
213 cf_error("Preferred lifetime must be at most Valid lifetime");
214
215 if (RADV_PREFIX->valid_lifetime_sensitive > RADV_PREFIX->preferred_lifetime_sensitive)
216 cf_error("Valid lifetime sensitive requires that Preferred lifetime is sensitive too");
217 };
218
219 radv_prefix_opts:
220 /* empty */
221 | radv_prefix_opts radv_prefix_item ';'
222 ;
223
224 radv_prefix_opt_list:
225 /* empty */
226 | '{' radv_prefix_opts '}'
227 ;
228
229 radv_prefix:
230 radv_prefix_start radv_prefix_opt_list radv_prefix_finish;
231
232
233
234 radv_rdnss_node: ipa
235 {
236 struct radv_rdnss_config *cf = cfg_allocz(sizeof(struct radv_rdnss_config));
237 add_tail(&radv_dns_list, NODE cf);
238
239 cf->server = $1;
240 cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
241 };
242
243 radv_rdnss_start:
244 {
245 RADV_RDNSS->lifetime = 0;
246 RADV_RDNSS->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
247 };
248
249 radv_rdnss_item:
250 | NS radv_rdnss_node
251 | LIFETIME radv_mult { RADV_RDNSS->lifetime = $2; RADV_RDNSS->lifetime_mult = radv_mult_val; }
252 ;
253
254 radv_rdnss_finish:
255 {
256 if (EMPTY_LIST(radv_dns_list))
257 cf_error("No nameserver in RDNSS section");
258
259 struct radv_rdnss_config *cf;
260 WALK_LIST(cf, radv_dns_list)
261 {
262 cf->lifetime = RADV_RDNSS->lifetime;
263 cf->lifetime_mult = RADV_RDNSS->lifetime_mult;
264 }
265 };
266
267 radv_rdnss_opts:
268 /* empty */
269 | radv_rdnss_opts radv_rdnss_item ';'
270 ;
271
272 radv_rdnss:
273 radv_rdnss_node
274 | '{' radv_rdnss_start radv_rdnss_opts '}' radv_rdnss_finish
275 ;
276
277
278 radv_dnssl_node: TEXT
279 {
280 struct radv_dnssl_config *cf = cfg_allocz(sizeof(struct radv_dnssl_config));
281 add_tail(&radv_dns_list, NODE cf);
282
283 cf->domain = $1;
284 cf->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
285
286 if (radv_process_domain(cf) < 0)
287 cf_error("Invalid domain dame");
288 };
289
290 radv_dnssl_start:
291 {
292 RADV_DNSSL->lifetime = 0;
293 RADV_DNSSL->lifetime_mult = DEFAULT_DNS_LIFETIME_MULT;
294 };
295
296 radv_dnssl_item:
297 | DOMAIN radv_dnssl_node
298 | LIFETIME radv_mult { RADV_DNSSL->lifetime = $2; RADV_DNSSL->lifetime_mult = radv_mult_val; }
299 ;
300
301 radv_dnssl_finish:
302 {
303 if (EMPTY_LIST(radv_dns_list))
304 cf_error("No domain in DNSSL section");
305
306 struct radv_dnssl_config *cf;
307 WALK_LIST(cf, radv_dns_list)
308 {
309 cf->lifetime = RADV_DNSSL->lifetime;
310 cf->lifetime_mult = RADV_DNSSL->lifetime_mult;
311 }
312 };
313
314 radv_dnssl_opts:
315 /* empty */
316 | radv_dnssl_opts radv_dnssl_item ';'
317 ;
318
319 radv_dnssl:
320 radv_dnssl_node
321 | '{' radv_dnssl_start radv_dnssl_opts '}' radv_dnssl_finish
322 ;
323
324
325 radv_mult:
326 expr { $$ = $1; radv_mult_val = 0; }
327 | MULT expr { $$ = 0; radv_mult_val = $2; if (($2 < 1) || ($2 > 254)) cf_error("Multiplier must be in range 1-254"); }
328 ;
329
330 radv_sensitive:
331 /* empty */ { $$ = (uint) -1; }
332 | SENSITIVE bool { $$ = $2; }
333 ;
334
335 dynamic_attr: RA_PREFERENCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_ENUM_RA_PREFERENCE, EA_RA_PREFERENCE); } ;
336 dynamic_attr: RA_LIFETIME { $$ = f_new_dynamic_attr(EAF_TYPE_INT, 0, T_INT, EA_RA_LIFETIME); } ;
337
338 CF_CODE
339
340 CF_END