]> git.ipfire.org Git - thirdparty/bird.git/blame - conf/flowspec.Y
Doc: BFD update
[thirdparty/bird.git] / conf / flowspec.Y
CommitLineData
77234bbb
OZ
1/*
2 * BIRD -- Flow specification (RFC 5575) grammar
3 *
4 * (c) 2016 CZ.NIC z.s.p.o.
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9CF_HDR
10
11#define PARSER 1
12
13#include "nest/bird.h"
77234bbb
OZ
14#include "lib/flowspec.h"
15
16
17CF_DEFINES
18
19struct flow_builder *this_flow;
20
21
22CF_DECLS
23
24%type <i32> flow_num_op flow_srcdst flow_logic_op flow_num_type_ flow_frag_val flow_neg
25%type <net_ptr> net_flow4_ net_flow6_ net_flow_
26
27CF_KEYWORDS(FLOW4, FLOW6, DST, SRC, PROTO, NEXT, HEADER, DPORT, SPORT, ICMP,
28 TYPE, CODE, TCP, FLAGS, LENGTH, DSCP, DONT_FRAGMENT, IS_FRAGMENT,
29 FIRST_FRAGMENT, LAST_FRAGMENT, FRAGMENT, LABEL, OFFSET)
30
31
32CF_GRAMMAR
33
34/* Network Flow Specification */
35
36flow_num_op:
734e9fb8
OZ
37 TRUE { $$ = FLOW_OP_TRUE; }
38 | '=' { $$ = FLOW_OP_EQ; }
39 | NEQ { $$ = FLOW_OP_NEQ; }
40 | '<' { $$ = FLOW_OP_LT; }
41 | LEQ { $$ = FLOW_OP_LEQ; }
42 | '>' { $$ = FLOW_OP_GT; }
43 | GEQ { $$ = FLOW_OP_GEQ; }
44 | FALSE { $$ = FLOW_OP_FALSE; }
77234bbb
OZ
45 ;
46
47flow_logic_op:
734e9fb8
OZ
48 OR { $$ = FLOW_OP_OR; }
49 | AND { $$ = FLOW_OP_AND; }
77234bbb
OZ
50 ;
51
52flow_num_type_:
53 PROTO { $$ = FLOW_TYPE_IP_PROTOCOL; }
54 | NEXT HEADER { $$ = FLOW_TYPE_NEXT_HEADER; }
55 | PORT { $$ = FLOW_TYPE_PORT; }
56 | DPORT { $$ = FLOW_TYPE_DST_PORT; }
57 | SPORT { $$ = FLOW_TYPE_SRC_PORT; }
58 | ICMP TYPE { $$ = FLOW_TYPE_ICMP_TYPE; }
59 | ICMP CODE { $$ = FLOW_TYPE_ICMP_CODE; }
60 | LENGTH { $$ = FLOW_TYPE_PACKET_LENGTH; }
61 | DSCP { $$ = FLOW_TYPE_DSCP; }
abc9ccc5 62 | LABEL { $$ = FLOW_TYPE_LABEL; }
77234bbb
OZ
63 ;
64
65flow_num_type: flow_num_type_{ flow_builder_set_type(this_flow, $1); };
66flow_flag_type: TCP FLAGS { flow_builder_set_type(this_flow, FLOW_TYPE_TCP_FLAGS); };
67flow_frag_type: FRAGMENT { flow_builder_set_type(this_flow, FLOW_TYPE_FRAGMENT); };
77234bbb
OZ
68
69flow_srcdst:
70 DST { $$ = FLOW_TYPE_DST_PREFIX; }
71 | SRC { $$ = FLOW_TYPE_SRC_PREFIX; }
72 ;
73
74flow_num_opts:
75 flow_num_op expr {
76 flow_check_cf_value_length(this_flow, $2);
77 flow_builder_add_op_val(this_flow, $1, $2);
78 }
79 | flow_num_opts flow_logic_op flow_num_op expr {
80 flow_check_cf_value_length(this_flow, $4);
81 flow_builder_add_op_val(this_flow, $2 | $3, $4);
82 }
83 | flow_num_opt_ext
84 | flow_num_opts OR flow_num_opt_ext
85 ;
86
87flow_num_opt_ext_expr:
88 expr {
89 flow_check_cf_value_length(this_flow, $1);
734e9fb8 90 flow_builder_add_op_val(this_flow, FLOW_OP_EQ, $1);
77234bbb
OZ
91 }
92 | expr DDOT expr {
93 flow_check_cf_value_length(this_flow, $1);
94 flow_check_cf_value_length(this_flow, $3);
734e9fb8
OZ
95 flow_builder_add_op_val(this_flow, FLOW_OP_GEQ, $1);
96 flow_builder_add_op_val(this_flow, FLOW_OP_AND | FLOW_OP_LEQ, $3);
77234bbb
OZ
97 }
98 ;
99
100flow_num_opt_ext:
101 flow_num_opt_ext_expr
102 | flow_num_opt_ext ',' flow_num_opt_ext_expr
103 ;
104
105flow_bmk_opts:
106 flow_neg expr '/' expr {
107 flow_check_cf_bmk_values(this_flow, $1, $2, $4);
108 flow_builder_add_val_mask(this_flow, $1, $2, $4);
109 }
110 | flow_bmk_opts flow_logic_op flow_neg expr '/' expr {
111 flow_check_cf_bmk_values(this_flow, $3, $4, $6);
112 flow_builder_add_val_mask(this_flow, $2 | $3, $4, $6);
113 }
114 | flow_bmk_opts ',' flow_neg expr '/' expr {
115 flow_check_cf_bmk_values(this_flow, $3, $4, $6);
116 flow_builder_add_val_mask(this_flow, 0x40 | $3, $4, $6); /* AND */
117 }
118 ;
119
120flow_neg:
121 /* empty */ { $$ = 0x00; }
122 | '!' { $$ = 0x02; }
123 ;
124
125flow_frag_val:
126 DONT_FRAGMENT { $$ = 1; }
127 | IS_FRAGMENT { $$ = 2; }
128 | FIRST_FRAGMENT { $$ = 4; }
129 | LAST_FRAGMENT { $$ = 8; }
130 ;
131
132flow_frag_opts:
133 flow_neg flow_frag_val {
134 flow_builder_add_val_mask(this_flow, 0, ($1 ? 0 : $2), $2);
135 }
136 | flow_frag_opts flow_logic_op flow_neg flow_frag_val {
137 flow_builder_add_val_mask(this_flow, $2, ($3 ? 0 : $4), $4);
138 }
139 | flow_frag_opts ',' flow_neg flow_frag_val {
140 flow_builder_add_val_mask(this_flow, 0x40, ($3 ? 0 : $4), $4); /* AND */
141 }
142 ;
143
144flow4_item:
141fb51f 145 flow_srcdst net_ip4 {
77234bbb
OZ
146 flow_builder_set_type(this_flow, $1);
147 flow_builder4_add_pfx(this_flow, (net_addr_ip4 *) &($2));
148 }
149 | flow_num_type flow_num_opts
150 | flow_flag_type flow_bmk_opts
151 | flow_frag_type flow_frag_opts
152 ;
153
154flow6_item:
155 flow_srcdst net_ip6 {
156 flow_builder_set_type(this_flow, $1);
157 flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), 0);
158 }
159 | flow_srcdst net_ip6 OFFSET NUM {
160 if ($4 > $2.pxlen)
161 cf_error("Prefix offset is higher than prefix length");
162 flow_builder_set_type(this_flow, $1);
163 flow_builder6_add_pfx(this_flow, (net_addr_ip6 *) &($2), $4);
164 }
165 | flow_num_type flow_num_opts
166 | flow_flag_type flow_bmk_opts
167 | flow_frag_type flow_frag_opts
77234bbb
OZ
168 ;
169
170flow4_opts:
171 /* empty */
172 | flow4_opts flow4_item ';'
173 ;
174
175flow6_opts:
176 /* empty */
177 | flow6_opts flow6_item ';'
178 ;
179
180flow_builder_init:
181{
182 if (this_flow == NULL)
37b64441 183 this_flow = flow_builder_init(config_pool); /* FIXME: This should be allocated from tmp in future */
77234bbb
OZ
184 else
185 flow_builder_clear(this_flow);
186};
187
188flow_builder_set_ipv4: { this_flow->ipv6 = 0; };
189flow_builder_set_ipv6: { this_flow->ipv6 = 1; };
190
191net_flow4_: FLOW4 '{' flow_builder_init flow_builder_set_ipv4 flow4_opts '}'
192{
193 $$ = (net_addr *) flow_builder4_finalize(this_flow, cfg_mem);
194 flow4_validate_cf((net_addr_flow4 *) $$);
195};
196
197net_flow6_: FLOW6 '{' flow_builder_init flow_builder_set_ipv6 flow6_opts '}'
198{
199 $$ = (net_addr *) flow_builder6_finalize(this_flow, cfg_mem);
200 flow6_validate_cf((net_addr_flow6 *) $$);
201};
202
203net_flow_: net_flow4_ | net_flow6_ ;
204
205
206CF_CODE
207
208CF_END