Annotation of embedaddon/bird2/conf/confbase.Y, revision 1.1.1.1
1.1 misho 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 "lib/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(uint val)
31: {
32: if (val > 0xFFFF)
33: cf_error("Value %u out of range (0-65535)", val);
34: }
35:
36: #define cf_assert(cond, ...) do { if (!(cond)) cf_error(__VA_ARGS__); } while (0)
37: static inline void cf_assert_symbol(const struct symbol *sym, uint class) {
38: switch (class) {
39: case SYM_PROTO: cf_assert(sym->class == SYM_PROTO, "Protocol name required"); break;
40: case SYM_TEMPLATE: cf_assert(sym->class == SYM_TEMPLATE, "Protocol template name required"); break;
41: case SYM_FUNCTION: cf_assert(sym->class == SYM_FUNCTION, "Function name required"); break;
42: case SYM_FILTER: cf_assert(sym->class == SYM_FILTER, "Filter name required"); break;
43: case SYM_TABLE: cf_assert(sym->class == SYM_TABLE, "Table name required"); break;
44: case SYM_ATTRIBUTE: cf_assert(sym->class == SYM_ATTRIBUTE, "Custom attribute name required"); break;
45: case SYM_VARIABLE: cf_assert((sym->class & ~0xff) == SYM_VARIABLE, "Variable name required"); break;
46: case SYM_CONSTANT: cf_assert((sym->class & ~0xff) == SYM_CONSTANT, "Constant name required"); break;
47: default: bug("This shall not happen");
48: }
49: }
50:
51: CF_DECLS
52:
53: %union {
54: uint i;
55: u32 i32;
56: u64 i64;
57: ip_addr a;
58: ip4_addr ip4;
59: ip6_addr ip6;
60: net_addr net;
61: net_addr *net_ptr;
62: struct symbol *s;
63: char *t;
64: struct rtable_config *r;
65: struct channel_config *cc;
66: struct f_inst *x;
67: struct {
68: struct f_inst *begin, *end;
69: } xp;
70: enum filter_return fret;
71: enum ec_subtype ecs;
72: struct f_dynamic_attr fda;
73: struct f_static_attr fsa;
74: struct f_lval flv;
75: struct f_line *fl;
76: const struct filter *f;
77: struct f_tree *e;
78: struct f_trie *trie;
79: struct f_val v;
80: struct password_item *p;
81: struct rt_show_data *ra;
82: struct sym_show_data *sd;
83: struct lsadb_show_data *ld;
84: struct mrt_dump_data *md;
85: struct iface *iface;
86: void *g;
87: btime time;
88: struct f_prefix px;
89: struct proto_spec ps;
90: struct channel_limit cl;
91: struct timeformat *tf;
92: mpls_label_stack *mls;
93: }
94:
95: %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
96: %token GEQ LEQ NEQ AND OR
97: %token PO PC
98: %token <i> NUM ENUM
99: %token <ip4> IP4
100: %token <ip6> IP6
101: %token <i64> VPN_RD
102: %token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED
103: %token <t> TEXT
104: %type <iface> ipa_scope
105:
106: %type <i> expr bool pxlen4
107: %type <time> expr_us time
108: %type <a> ipa
109: %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
110: %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
111: %type <mls> label_stack_start label_stack
112:
113: %type <t> text opttext
114: %type <s> symbol
115:
116: %nonassoc PREFIX_DUMMY
117: %left AND OR
118: %nonassoc '=' '<' '>' '~' GEQ LEQ NEQ NMA PO PC
119: %left '+' '-'
120: %left '*' '/' '%'
121: %left '!'
122: %nonassoc '.'
123:
124: %start config
125:
126: CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM)
127:
128: CF_GRAMMAR
129:
130: /* Basic config file structure */
131:
132: config: conf_entries END { return 0; }
133: | CLI_MARKER cli_cmd { return 0; }
134: ;
135:
136: conf_entries:
137: /* EMPTY */
138: | conf_entries conf
139: ;
140:
141: conf: ';' ;
142:
143:
144: /* Constant expressions */
145:
146: conf: definition ;
147:
148: definition:
149: DEFINE symbol '=' term ';' {
150: struct f_val *val = cfg_alloc(sizeof(struct f_val));
151: if (f_eval(f_linearize($4), cfg_mem, val) > F_RETURN) cf_error("Runtime error");
152: cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
153: }
154: ;
155:
156: expr:
157: NUM
158: | '(' term ')' { $$ = f_eval_int(f_linearize($2)); }
159: | CF_SYM_KNOWN {
160: if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
161: $$ = SYM_VAL($1).i; }
162: ;
163:
164: expr_us:
165: expr S { $$ = $1 S_; }
166: | expr MS { $$ = $1 MS_; }
167: | expr US { $$ = $1 US_; }
168: ;
169:
170: symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ;
171:
172: /* Switches */
173:
174: bool:
175: expr { $$ = !!$1; }
176: | ON { $$ = 1; }
177: | YES { $$ = 1; }
178: | OFF { $$ = 0; }
179: | NO { $$ = 0; }
180: | /* Silence means agreement */ { $$ = 1; }
181: ;
182:
183:
184: /* Addresses */
185:
186: ipa:
187: IP4 { $$ = ipa_from_ip4($1); }
188: | IP6 { $$ = ipa_from_ip6($1); }
189: | CF_SYM_KNOWN {
190: if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address constant expected");
191: $$ = SYM_VAL($1).ip;
192: }
193: ;
194:
195: ipa_scope:
196: /* empty */ { $$ = NULL; }
197: | '%' symbol { $$ = if_get_by_name($2->name); }
198: ;
199:
200:
201: /* Networks - internal */
202:
203: pxlen4:
204: '/' NUM {
205: if ($2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %u", $2);
206: $$ = $2;
207: }
208: ;
209:
210: net_ip4_: IP4 pxlen4
211: {
212: net_fill_ip4(&($$), $1, $2);
213:
214: net_addr_ip4 *n = (void *) &($$);
215: if (!net_validate_ip4(n))
216: cf_error("Invalid IPv4 prefix %I4/%d, maybe you wanted %I4/%d",
217: n->prefix, n->pxlen, ip4_and(n->prefix, ip4_mkmask(n->pxlen)), n->pxlen);
218: };
219:
220: net_ip6_: IP6 '/' NUM
221: {
222: if ($3 > IP6_MAX_PREFIX_LENGTH)
223: cf_error("Invalid prefix length %u", $3);
224:
225: net_fill_ip6(&($$), $1, $3);
226:
227: net_addr_ip6 *n = (void *) &($$);
228: if (!net_validate_ip6(n))
229: cf_error("Invalid IPv6 prefix %I6/%d, maybe you wanted %I6/%d",
230: n->prefix, n->pxlen, ip6_and(n->prefix, ip6_mkmask(n->pxlen)), n->pxlen);
231: };
232:
233: net_ip6_sadr_: IP6 '/' NUM FROM IP6 '/' NUM
234: {
235: if ($3 > IP6_MAX_PREFIX_LENGTH)
236: cf_error("Invalid prefix length %u", $3);
237:
238: if ($7 > IP6_MAX_PREFIX_LENGTH)
239: cf_error("Invalid prefix length %u", $7);
240:
241: $$ = cfg_alloc(sizeof(net_addr_ip6_sadr));
242: net_fill_ip6_sadr($$, $1, $3, $5, $7);
243:
244: net_addr_ip6_sadr *n = (void *) $$;
245: if (!net_validate_ip6_sadr(n))
246: cf_error("Invalid SADR IPv6 prefix %I6/%d from %I6/%d, maybe you wanted %I6/%d from %I6/%d",
247: n->dst_prefix, n->dst_pxlen, n->src_prefix, n->src_pxlen,
248: ip6_and(n->dst_prefix, ip6_mkmask(n->dst_pxlen)), n->dst_pxlen,
249: ip6_and(n->src_prefix, ip6_mkmask(n->src_pxlen)), n->src_pxlen);
250: };
251:
252: net_vpn4_: VPN_RD net_ip4_
253: {
254: $$ = cfg_alloc(sizeof(net_addr_vpn4));
255: net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
256: }
257:
258: net_vpn6_: VPN_RD net_ip6_
259: {
260: $$ = cfg_alloc(sizeof(net_addr_vpn6));
261: net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
262: }
263:
264: net_roa4_: net_ip4_ MAX NUM AS NUM
265: {
266: $$ = cfg_alloc(sizeof(net_addr_roa4));
267: net_fill_roa4($$, net4_prefix(&$1), net4_pxlen(&$1), $3, $5);
268: if ($3 < net4_pxlen(&$1) || $3 > IP4_MAX_PREFIX_LENGTH)
269: cf_error("Invalid max prefix length %u", $3);
270: };
271:
272: net_roa6_: net_ip6_ MAX NUM AS NUM
273: {
274: $$ = cfg_alloc(sizeof(net_addr_roa6));
275: net_fill_roa6($$, net6_prefix(&$1), net6_pxlen(&$1), $3, $5);
276: if ($3 < net6_pxlen(&$1) || $3 > IP6_MAX_PREFIX_LENGTH)
277: cf_error("Invalid max prefix length %u", $3);
278: };
279:
280: net_mpls_: MPLS NUM
281: {
282: $$ = cfg_alloc(sizeof(net_addr_roa6));
283: net_fill_mpls($$, $2);
284: }
285:
286: net_ip_: net_ip4_ | net_ip6_ ;
287: net_vpn_: net_vpn4_ | net_vpn6_ ;
288: net_roa_: net_roa4_ | net_roa6_ ;
289:
290: net_:
291: net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
292: | net_vpn_
293: | net_roa_
294: | net_flow_
295: | net_ip6_sadr_
296: | net_mpls_
297: ;
298:
299:
300: /* Networks - regular */
301:
302: net_ip6:
303: net_ip6_
304: | CF_SYM_KNOWN {
305: if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6))
306: cf_error("IPv6 network constant expected");
307: $$ = * SYM_VAL($1).net;
308: }
309: ;
310:
311: net_ip:
312: net_ip_
313: | CF_SYM_KNOWN {
314: if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net))
315: cf_error("IP network constant expected");
316: $$ = * SYM_VAL($1).net;
317: }
318: ;
319:
320: net_any:
321: net_
322: | CF_SYM_KNOWN {
323: if ($1->class != (SYM_CONSTANT | T_NET))
324: cf_error("Network constant expected");
325: $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */
326: }
327: ;
328:
329: net_or_ipa:
330: net_ip4_
331: | net_ip6_
332: | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); }
333: | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); }
334: | CF_SYM_KNOWN {
335: if ($1->class == (SYM_CONSTANT | T_IP))
336: net_fill_ip_host(&($$), SYM_VAL($1).ip);
337: else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net))
338: $$ = * SYM_VAL($1).net;
339: else
340: cf_error("IP address or network constant expected");
341: }
342: ;
343:
344: label_stack_start: NUM
345: {
346: $$ = cfg_allocz(sizeof(mpls_label_stack));
347: $$->len = 1;
348: $$->stack[0] = $1;
349: };
350:
351: label_stack:
352: label_stack_start
353: | label_stack '/' NUM {
354: if ($1->len >= MPLS_MAX_LABEL_STACK)
355: cf_error("Too many labels in stack");
356: $1->stack[$1->len++] = $3;
357: $$ = $1;
358: }
359: ;
360:
361: time:
362: TEXT {
363: $$ = tm_parse_time($1);
364: if (!$$)
365: cf_error("Invalid date/time");
366: }
367: ;
368:
369: text:
370: TEXT
371: | CF_SYM_KNOWN {
372: if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String constant expected");
373: $$ = SYM_VAL($1).s;
374: }
375: ;
376:
377: opttext:
378: TEXT
379: | /* empty */ { $$ = NULL; }
380: ;
381:
382:
383: CF_CODE
384:
385: CF_END
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>