1use inetnum::addr::Prefix;
4use crate::bgp::{nlri::common::prefix_bits_to_bytes, types::Afi};
5use crate::util::parser::ParseError;
6use log::debug;
7use octseq::{Octets, Parser};
8
9use std::net::IpAddr;
10
11fn op_to_len(op: u8) -> usize {
12 match (op & 0b00110000) >> 4 {
13 0b00 => 1,
14 0b01 => 2,
15 0b10 => 4,
16 0b11 => 8,
17 _ => panic!("impossible len bits in NumericOp")
18 }
19}
20
21pub struct NumericOp(u8, u64);
22impl NumericOp {
23 pub fn end_of_list(&self) -> bool {
24 self.0 & 0x80 == 0x80
25 }
26
27 pub fn and(&self) -> bool {
28 self.0 & 0x40 == 0x40
29 }
30
31 pub fn length(&self) -> usize {
32 op_to_len(self.0)
33 }
34
35 pub fn value(&self) -> u64 {
36 self.1
37 }
38}
39
40pub struct BitmaskOp(u8, u64);
41impl BitmaskOp {
42 pub fn end_of_list(&self) -> bool {
43 self.0 & 0x80 == 0x80
44 }
45
46 pub fn value(&self) -> u64 {
47 self.1
48 }
49}
50
51
52#[derive(Copy, Clone, Debug)]
53pub enum Component<Octets> {
54 DestinationPrefix(Prefix),
55 SourcePrefix(Prefix),
56 IpProtocol(Octets),
57 Port(Octets),
58 DestinationPort(Octets),
59 SourcePort(Octets),
60 IcmpType(Octets),
61 IcmpCode(Octets),
62 TcpFlags(Octets), PacketLength(Octets),
64 DSCP(Octets),
65 Fragment(Octets),
66}
67
68impl NumericOp {
69 fn parse<R: Octets + ?Sized>(parser: &mut Parser<'_, R>)
70 -> Result<Self, ParseError>
71 {
72 let op = parser.parse_u8()?;
73 let value = match op_to_len(op) {
74 1 => parser.parse_u8()? as u64,
75 2 => parser.parse_u16_be()? as u64,
76 4 => parser.parse_u32_be()? as u64,
77 8 => parser.parse_u64_be()?,
78 _ => panic!("illegal case"),
79 };
80 Ok(Self(op, value))
81 }
82}
83
84impl BitmaskOp {
85 fn parse<R: Octets + ?Sized>(parser: &mut Parser<'_, R>)
86 -> Result<Self, ParseError>
87 {
88 let op = parser.parse_u8()?;
89 let value = match op_to_len(op) {
90 1 => parser.parse_u8()? as u64,
91 2 => parser.parse_u16_be()? as u64,
92 4 => parser.parse_u32_be()? as u64,
93 8 => parser.parse_u64_be()?,
94 _ => panic!("illegal case"),
95 };
96 Ok(Self(op, value))
97 }
98}
99
100fn parse_prefix<R: Octets + ?Sized>(
101 parser: &mut Parser<'_, R>,
102 afi: Afi,
103 prefix_bits: u8
104) -> Result<Prefix, ParseError>
105{
106 let prefix_bytes = prefix_bits_to_bytes(prefix_bits);
107 let prefix = match (afi, prefix_bytes) {
108 (Afi::Ipv4, 0) => {
109 Prefix::new_v4(0.into(), 0)?
110 },
111 (Afi::Ipv4, _b @ 5..) => {
112 return Err(ParseError::form_error("illegal byte size for IPv4 NLRI"))
113 },
114 (Afi::Ipv4, _) => {
115 let mut b = [0u8; 4];
116 b[..prefix_bytes].copy_from_slice(parser.peek(prefix_bytes)?);
117 parser.advance(prefix_bytes)?;
118 Prefix::new(IpAddr::from(b), prefix_bits).map_err(|_e|
119 ParseError::form_error("prefix parsing failed")
120 )?
121 }
122 (Afi::Ipv6, 0) => {
123 Prefix::new_v6(0.into(), 0)?
124 },
125 (Afi::Ipv6, _b @ 17..) => {
126 return Err(ParseError::form_error("illegal byte size for IPv6 NLRI"))
127 },
128 (Afi::Ipv6, _) => {
129 let mut b = [0u8; 16];
130 b[..prefix_bytes].copy_from_slice(parser.peek(prefix_bytes)?);
131 parser.advance(prefix_bytes)?;
132 Prefix::new(IpAddr::from(b), prefix_bits).map_err(|_e|
133 ParseError::form_error("prefix parsing failed")
134 )?
135 },
136 (_, _) => {
137 panic!("unimplemented")
138 }
139 };
140 Ok(prefix)
141}
142
143impl<Octs: Octets> Component<Octs> {
144 pub(crate) fn parse<'a, R>(parser: &mut Parser<'a, R>)
145 -> Result<Self, ParseError>
146 where
147 R: Octets<Range<'a> = Octs> + ?Sized
148 {
149 let typ = parser.parse_u8()?;
150 let res = match typ {
151 1 => {
152 let prefix_bits = parser.parse_u8()?;
153 let pfx = parse_prefix(parser, Afi::Ipv4, prefix_bits)?;
154 Component::DestinationPrefix(pfx)
155 },
156 2 => {
157 let prefix_bits = parser.parse_u8()?;
158 let pfx = parse_prefix(parser, Afi::Ipv4, prefix_bits)?;
159 Component::SourcePrefix(pfx)
160 },
161 3 => {
162 let pos = parser.pos();
163 let mut done = false;
164 while !done {
165 let op = NumericOp::parse(parser)?;
166 done = op.end_of_list();
167 }
168 let octets_len = parser.pos() - pos;
169 parser.seek(pos)?;
170 Component::IpProtocol(
171 parser.parse_octets(octets_len)?
172 )
173 },
174 4 => {
175 let pos = parser.pos();
176 let mut done = false;
177 while !done {
178 let op = NumericOp::parse(parser)?;
179 done = op.end_of_list();
180 }
181 let octets_len = parser.pos() - pos;
182 parser.seek(pos)?;
183 Component::Port(
184 parser.parse_octets(octets_len)?
185 )
186 },
187 5 => {
188 let pos = parser.pos();
189 let mut done = false;
190 while !done {
191 let op = NumericOp::parse(parser)?;
192 done = op.end_of_list();
193 }
194 let octets_len = parser.pos() - pos;
195 parser.seek(pos)?;
196 Component::DestinationPort(
197 parser.parse_octets(octets_len)?
198 )
199 },
200 6 => {
201 let pos = parser.pos();
202 let mut done = false;
203 while !done {
204 let op = NumericOp::parse(parser)?;
205 done = op.end_of_list();
206 }
207 let octets_len = parser.pos() - pos;
208 parser.seek(pos)?;
209 Component::SourcePort(
210 parser.parse_octets(octets_len)?
211 )
212 },
213 7 => {
214 let pos = parser.pos();
215 let mut done = false;
216 while !done {
217 let op = NumericOp::parse(parser)?;
218 done = op.end_of_list();
219 }
220 let octets_len = parser.pos() - pos;
221 parser.seek(pos)?;
222 Component::IcmpType(
223 parser.parse_octets(octets_len)?
224 )
225 },
226 8 => {
227 let pos = parser.pos();
228 let mut done = false;
229 while !done {
230 let op = NumericOp::parse(parser)?;
231 done = op.end_of_list();
232 }
233 let octets_len = parser.pos() - pos;
234 parser.seek(pos)?;
235 Component::IcmpCode(
236 parser.parse_octets(octets_len)?
237 )
238 },
239 9 => {
240 let pos = parser.pos();
241 let mut done = false;
242 while !done {
243 let op = BitmaskOp::parse(parser)?;
244 done = op.end_of_list();
245 }
246 let octets_len = parser.pos() - pos;
247 parser.seek(pos)?;
248 Component::TcpFlags(
249 parser.parse_octets(octets_len)?
250 )
251 },
252 10 => {
253 let pos = parser.pos();
254 let mut done = false;
255 while !done {
256 let op = NumericOp::parse(parser)?;
257 done = op.end_of_list();
258 }
259 let octets_len = parser.pos() - pos;
260 parser.seek(pos)?;
261 Component::PacketLength(
262 parser.parse_octets(octets_len)?
263 )
264 },
265 11 => {
266 let pos = parser.pos();
267 let mut done = false;
268 while !done {
269 let op = NumericOp::parse(parser)?;
270 done = op.end_of_list();
271 }
272 let octets_len = parser.pos() - pos;
273 parser.seek(pos)?;
274 Component::DSCP(
275 parser.parse_octets(octets_len)?
276 )
277 },
278 12 => {
279 let pos = parser.pos();
280 let mut done = false;
281 while !done {
282 let op = BitmaskOp::parse(parser)?;
283 done = op.end_of_list();
284 }
285 let octets_len = parser.pos() - pos;
286 parser.seek(pos)?;
287 Component::Fragment(
288 parser.parse_octets(octets_len)?
289 )
290 },
291 _ => {
292 debug!("unimplemented flowspec type {}", typ);
293 return Err(ParseError::Unsupported)
294 }
295 };
296
297 Ok(res)
298 }
299}
300
301
302