1use super::*;
2use crate::models::NetworkPrefix;
3use ipnet::IpNet;
4
5#[cfg(test)]
6use std::str::FromStr;
7
8pub fn parse_flowspec_nlri(data: &[u8]) -> Result<FlowSpecNlri, FlowSpecError> {
10 let mut offset = 0;
11 let length = parse_length(data, &mut offset)?;
12
13 if offset + length as usize > data.len() {
14 return Err(FlowSpecError::InsufficientData);
15 }
16
17 let end_offset = offset + length as usize;
18 let mut components = Vec::new();
19 let mut last_type = 0u8;
20
21 while offset < end_offset {
22 let component_type = data[offset];
23 offset += 1;
24
25 if component_type <= last_type {
27 return Err(FlowSpecError::InvalidComponentOrder {
28 expected_greater_than: last_type,
29 found: component_type,
30 });
31 }
32 last_type = component_type;
33
34 let component = match component_type {
35 1 => parse_destination_prefix(data, &mut offset)?,
36 2 => parse_source_prefix(data, &mut offset)?,
37 3 => parse_ip_protocol(data, &mut offset)?,
38 4 => parse_port(data, &mut offset)?,
39 5 => parse_destination_port(data, &mut offset)?,
40 6 => parse_source_port(data, &mut offset)?,
41 7 => parse_icmp_type(data, &mut offset)?,
42 8 => parse_icmp_code(data, &mut offset)?,
43 9 => parse_tcp_flags(data, &mut offset)?,
44 10 => parse_packet_length(data, &mut offset)?,
45 11 => parse_dscp(data, &mut offset)?,
46 12 => parse_fragment(data, &mut offset)?,
47 13 => parse_flow_label(data, &mut offset)?,
48 _ => return Err(FlowSpecError::InvalidComponentType(component_type)),
49 };
50
51 components.push(component);
52 }
53
54 Ok(FlowSpecNlri { components })
55}
56
57pub fn encode_flowspec_nlri(nlri: &FlowSpecNlri) -> Vec<u8> {
59 let mut data = Vec::new();
60
61 for component in &nlri.components {
63 data.push(component.component_type());
64
65 match component {
66 FlowSpecComponent::DestinationPrefix(prefix)
67 | FlowSpecComponent::SourcePrefix(prefix) => {
68 encode_prefix(prefix, &mut data);
69 }
70 FlowSpecComponent::DestinationIpv6Prefix { offset, prefix }
71 | FlowSpecComponent::SourceIpv6Prefix { offset, prefix } => {
72 encode_ipv6_prefix(*offset, prefix, &mut data);
73 }
74 FlowSpecComponent::IpProtocol(ops)
75 | FlowSpecComponent::Port(ops)
76 | FlowSpecComponent::DestinationPort(ops)
77 | FlowSpecComponent::SourcePort(ops)
78 | FlowSpecComponent::IcmpType(ops)
79 | FlowSpecComponent::IcmpCode(ops)
80 | FlowSpecComponent::PacketLength(ops)
81 | FlowSpecComponent::Dscp(ops)
82 | FlowSpecComponent::FlowLabel(ops) => {
83 encode_numeric_operators(ops, &mut data);
84 }
85 FlowSpecComponent::TcpFlags(ops) | FlowSpecComponent::Fragment(ops) => {
86 encode_bitmask_operators(ops, &mut data);
87 }
88 }
89 }
90
91 let mut result = Vec::new();
93 encode_length(data.len() as u16, &mut result);
94 result.extend(data);
95 result
96}
97
98pub(crate) fn parse_length(data: &[u8], offset: &mut usize) -> Result<u16, FlowSpecError> {
100 if *offset >= data.len() {
101 return Err(FlowSpecError::InsufficientData);
102 }
103
104 let first_byte = data[*offset];
105 *offset += 1;
106
107 if first_byte < 240 {
108 Ok(first_byte as u16)
109 } else {
110 if *offset >= data.len() {
111 return Err(FlowSpecError::InsufficientData);
112 }
113 let second_byte = data[*offset];
114 *offset += 1;
115 Ok(((first_byte & 0x0F) as u16) << 8 | second_byte as u16)
116 }
117}
118
119pub(crate) fn encode_length(length: u16, data: &mut Vec<u8>) {
121 if length < 240 {
122 data.push(length as u8);
123 } else {
124 data.push(0xF0 | ((length >> 8) as u8));
125 data.push(length as u8);
126 }
127}
128
129fn parse_prefix_component(data: &[u8], offset: &mut usize) -> Result<NetworkPrefix, FlowSpecError> {
131 if *offset >= data.len() {
132 return Err(FlowSpecError::InsufficientData);
133 }
134
135 let prefix_len = data[*offset];
136 *offset += 1;
137
138 let prefix_bytes = prefix_len.div_ceil(8);
139 if *offset + prefix_bytes as usize > data.len() {
140 return Err(FlowSpecError::InsufficientData);
141 }
142
143 let prefix_data = &data[*offset..*offset + prefix_bytes as usize];
144 *offset += prefix_bytes as usize;
145
146 let prefix = if prefix_bytes <= 4 {
148 let mut addr_bytes = [0u8; 4];
150 addr_bytes[..prefix_data.len()].copy_from_slice(prefix_data);
151 let addr = std::net::Ipv4Addr::from(addr_bytes);
152 let ipnet = IpNet::V4(
153 ipnet::Ipv4Net::new(addr, prefix_len).map_err(|_| FlowSpecError::InvalidPrefix)?,
154 );
155 NetworkPrefix::new(ipnet, None)
156 } else {
157 let mut addr_bytes = [0u8; 16];
159 addr_bytes[..prefix_data.len()].copy_from_slice(prefix_data);
160 let addr = std::net::Ipv6Addr::from(addr_bytes);
161 let ipnet = IpNet::V6(
162 ipnet::Ipv6Net::new(addr, prefix_len).map_err(|_| FlowSpecError::InvalidPrefix)?,
163 );
164 NetworkPrefix::new(ipnet, None)
165 };
166
167 Ok(prefix)
168}
169
170fn parse_destination_prefix(
172 data: &[u8],
173 offset: &mut usize,
174) -> Result<FlowSpecComponent, FlowSpecError> {
175 let prefix = parse_prefix_component(data, offset)?;
176 Ok(FlowSpecComponent::DestinationPrefix(prefix))
177}
178
179fn parse_source_prefix(
181 data: &[u8],
182 offset: &mut usize,
183) -> Result<FlowSpecComponent, FlowSpecError> {
184 let prefix = parse_prefix_component(data, offset)?;
185 Ok(FlowSpecComponent::SourcePrefix(prefix))
186}
187
188fn parse_numeric_operators(
190 data: &[u8],
191 offset: &mut usize,
192) -> Result<Vec<NumericOperator>, FlowSpecError> {
193 let mut operators = Vec::new();
194
195 loop {
196 if *offset >= data.len() {
197 return Err(FlowSpecError::InsufficientData);
198 }
199
200 let operator_byte = data[*offset];
201 *offset += 1;
202
203 let value_length = match (operator_byte >> 4) & 0x03 {
204 0 => 1,
205 1 => 2,
206 2 => 4,
207 3 => 8,
208 _ => {
209 return Err(FlowSpecError::InvalidValueLength(
210 (operator_byte >> 4) & 0x03,
211 ))
212 }
213 };
214
215 if *offset + value_length > data.len() {
216 return Err(FlowSpecError::InsufficientData);
217 }
218
219 let value = read_value(&data[*offset..*offset + value_length]);
220 *offset += value_length;
221
222 let operator = NumericOperator::from_byte_and_value(operator_byte, value)?;
223 let is_end = operator.end_of_list;
224 operators.push(operator);
225
226 if is_end {
227 break;
228 }
229 }
230
231 Ok(operators)
232}
233
234fn parse_bitmask_operators(
236 data: &[u8],
237 offset: &mut usize,
238) -> Result<Vec<BitmaskOperator>, FlowSpecError> {
239 let mut operators = Vec::new();
240
241 loop {
242 if *offset >= data.len() {
243 return Err(FlowSpecError::InsufficientData);
244 }
245
246 let operator_byte = data[*offset];
247 *offset += 1;
248
249 let value_length = match (operator_byte >> 4) & 0x03 {
250 0 => 1,
251 1 => 2,
252 2 => 4,
253 3 => 8,
254 _ => {
255 return Err(FlowSpecError::InvalidValueLength(
256 (operator_byte >> 4) & 0x03,
257 ))
258 }
259 };
260
261 if *offset + value_length > data.len() {
262 return Err(FlowSpecError::InsufficientData);
263 }
264
265 let bitmask = read_value(&data[*offset..*offset + value_length]);
266 *offset += value_length;
267
268 let operator = BitmaskOperator::from_byte_and_value(operator_byte, bitmask)?;
269 let is_end = operator.end_of_list;
270 operators.push(operator);
271
272 if is_end {
273 break;
274 }
275 }
276
277 Ok(operators)
278}
279
280fn read_value(bytes: &[u8]) -> u64 {
282 let mut value = 0u64;
283 for &byte in bytes {
284 value = (value << 8) | byte as u64;
285 }
286 value
287}
288
289fn write_value(value: u64, length: usize, data: &mut Vec<u8>) {
291 for i in (0..length).rev() {
292 data.push((value >> (i * 8)) as u8);
293 }
294}
295
296fn parse_ip_protocol(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
298 let operators = parse_numeric_operators(data, offset)?;
299 Ok(FlowSpecComponent::IpProtocol(operators))
300}
301
302fn parse_port(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
303 let operators = parse_numeric_operators(data, offset)?;
304 Ok(FlowSpecComponent::Port(operators))
305}
306
307fn parse_destination_port(
308 data: &[u8],
309 offset: &mut usize,
310) -> Result<FlowSpecComponent, FlowSpecError> {
311 let operators = parse_numeric_operators(data, offset)?;
312 Ok(FlowSpecComponent::DestinationPort(operators))
313}
314
315fn parse_source_port(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
316 let operators = parse_numeric_operators(data, offset)?;
317 Ok(FlowSpecComponent::SourcePort(operators))
318}
319
320fn parse_icmp_type(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
321 let operators = parse_numeric_operators(data, offset)?;
322 Ok(FlowSpecComponent::IcmpType(operators))
323}
324
325fn parse_icmp_code(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
326 let operators = parse_numeric_operators(data, offset)?;
327 Ok(FlowSpecComponent::IcmpCode(operators))
328}
329
330fn parse_tcp_flags(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
331 let operators = parse_bitmask_operators(data, offset)?;
332 Ok(FlowSpecComponent::TcpFlags(operators))
333}
334
335fn parse_packet_length(
336 data: &[u8],
337 offset: &mut usize,
338) -> Result<FlowSpecComponent, FlowSpecError> {
339 let operators = parse_numeric_operators(data, offset)?;
340 Ok(FlowSpecComponent::PacketLength(operators))
341}
342
343fn parse_dscp(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
344 let operators = parse_numeric_operators(data, offset)?;
345 Ok(FlowSpecComponent::Dscp(operators))
346}
347
348fn parse_fragment(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
349 let operators = parse_bitmask_operators(data, offset)?;
350 Ok(FlowSpecComponent::Fragment(operators))
351}
352
353fn parse_flow_label(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
354 let operators = parse_numeric_operators(data, offset)?;
355 Ok(FlowSpecComponent::FlowLabel(operators))
356}
357
358fn encode_prefix(prefix: &NetworkPrefix, data: &mut Vec<u8>) {
360 let prefix_len = prefix.prefix.prefix_len();
361 data.push(prefix_len);
362
363 let prefix_bytes = prefix_len.div_ceil(8);
364 let addr_bytes = match prefix.prefix.addr() {
365 std::net::IpAddr::V4(addr) => addr.octets().to_vec(),
366 std::net::IpAddr::V6(addr) => addr.octets().to_vec(),
367 };
368
369 data.extend(&addr_bytes[..prefix_bytes as usize]);
370}
371
372fn encode_ipv6_prefix(offset: u8, prefix: &NetworkPrefix, data: &mut Vec<u8>) {
373 data.push(prefix.prefix.prefix_len());
374 data.push(offset);
375
376 let prefix_bytes = prefix.prefix.prefix_len().div_ceil(8);
377 if let std::net::IpAddr::V6(addr) = prefix.prefix.addr() {
378 let addr_bytes = addr.octets();
379 data.extend(&addr_bytes[..prefix_bytes as usize]);
380 }
381}
382
383fn encode_numeric_operators(operators: &[NumericOperator], data: &mut Vec<u8>) {
384 for operator in operators {
385 data.push(operator.to_byte());
386 write_value(operator.value, operator.value_length as usize, data);
387 }
388}
389
390fn encode_bitmask_operators(operators: &[BitmaskOperator], data: &mut Vec<u8>) {
391 for operator in operators {
392 data.push(operator.to_byte());
393 write_value(operator.bitmask, operator.value_length as usize, data);
394 }
395}
396
397#[cfg(test)]
398mod tests {
399 use super::*;
400
401 #[test]
402 fn test_length_encoding() {
403 let mut data = Vec::new();
405 encode_length(100, &mut data);
406 assert_eq!(data, vec![100]);
407
408 let mut offset = 0;
409 let parsed_len = parse_length(&data, &mut offset).unwrap();
410 assert_eq!(parsed_len, 100);
411 assert_eq!(offset, 1);
412
413 let mut data = Vec::new();
415 encode_length(1000, &mut data);
416 assert_eq!(data, vec![0xF3, 0xE8]); let mut offset = 0;
419 let parsed_len = parse_length(&data, &mut offset).unwrap();
420 assert_eq!(parsed_len, 1000);
421 assert_eq!(offset, 2);
422 }
423
424 #[test]
425 fn test_read_write_value() {
426 assert_eq!(read_value(&[0x25]), 0x25);
428
429 assert_eq!(read_value(&[0x01, 0xBB]), 443);
431
432 assert_eq!(read_value(&[0x00, 0x00, 0x00, 0x50]), 80);
434
435 let mut data = Vec::new();
437 write_value(443, 2, &mut data);
438 assert_eq!(data, vec![0x01, 0xBB]);
439 }
440
441 #[test]
442 fn test_simple_nlri_parsing() {
443 let data = vec![
445 0x08, 0x01, 0x18, 0xC0, 0x00, 0x02, 0x03, 0x81, 0x06, ];
453
454 let nlri = parse_flowspec_nlri(&data).unwrap();
455 assert_eq!(nlri.components.len(), 2);
456
457 match &nlri.components[0] {
458 FlowSpecComponent::DestinationPrefix(prefix) => {
459 assert_eq!(prefix.to_string(), "192.0.2.0/24");
460 }
461 _ => panic!("Expected destination prefix"),
462 }
463
464 match &nlri.components[1] {
465 FlowSpecComponent::IpProtocol(ops) => {
466 assert_eq!(ops.len(), 1);
467 assert_eq!(ops[0].value, 6);
468 assert!(ops[0].equal);
469 }
470 _ => panic!("Expected IP protocol"),
471 }
472 }
473
474 #[test]
475 fn test_nlri_round_trip() {
476 let original_nlri = FlowSpecNlri::new(vec![
477 FlowSpecComponent::DestinationPrefix(NetworkPrefix::from_str("192.0.2.0/24").unwrap()),
478 FlowSpecComponent::IpProtocol(vec![NumericOperator::equal_to(6)]),
479 FlowSpecComponent::DestinationPort(vec![NumericOperator::equal_to(80)]),
480 ]);
481
482 let encoded = encode_flowspec_nlri(&original_nlri);
483 let parsed_nlri = parse_flowspec_nlri(&encoded).unwrap();
484
485 assert_eq!(original_nlri, parsed_nlri);
486 }
487}