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 if prefix_len > 128 {
143 return Err(FlowSpecError::InvalidPrefix);
144 }
145
146 let prefix_bytes = prefix_len.div_ceil(8);
147 if *offset + prefix_bytes as usize > data.len() {
148 return Err(FlowSpecError::InsufficientData);
149 }
150
151 let prefix_data = &data[*offset..*offset + prefix_bytes as usize];
152 *offset += prefix_bytes as usize;
153
154 let prefix = if prefix_bytes <= 4 {
156 let mut addr_bytes = [0u8; 4];
158 addr_bytes[..prefix_data.len()].copy_from_slice(prefix_data);
159 let addr = std::net::Ipv4Addr::from(addr_bytes);
160 let ipnet = IpNet::V4(
161 ipnet::Ipv4Net::new(addr, prefix_len).map_err(|_| FlowSpecError::InvalidPrefix)?,
162 );
163 NetworkPrefix::new(ipnet, None)
164 } else {
165 let mut addr_bytes = [0u8; 16];
167 addr_bytes[..prefix_data.len()].copy_from_slice(prefix_data);
168 let addr = std::net::Ipv6Addr::from(addr_bytes);
169 let ipnet = IpNet::V6(
170 ipnet::Ipv6Net::new(addr, prefix_len).map_err(|_| FlowSpecError::InvalidPrefix)?,
171 );
172 NetworkPrefix::new(ipnet, None)
173 };
174
175 Ok(prefix)
176}
177
178fn parse_destination_prefix(
180 data: &[u8],
181 offset: &mut usize,
182) -> Result<FlowSpecComponent, FlowSpecError> {
183 let prefix = parse_prefix_component(data, offset)?;
184 Ok(FlowSpecComponent::DestinationPrefix(prefix))
185}
186
187fn parse_source_prefix(
189 data: &[u8],
190 offset: &mut usize,
191) -> Result<FlowSpecComponent, FlowSpecError> {
192 let prefix = parse_prefix_component(data, offset)?;
193 Ok(FlowSpecComponent::SourcePrefix(prefix))
194}
195
196fn parse_numeric_operators(
198 data: &[u8],
199 offset: &mut usize,
200) -> Result<Vec<NumericOperator>, FlowSpecError> {
201 let mut operators = Vec::new();
202
203 loop {
204 if *offset >= data.len() {
205 return Err(FlowSpecError::InsufficientData);
206 }
207
208 let operator_byte = data[*offset];
209 *offset += 1;
210
211 let value_length = match (operator_byte >> 4) & 0x03 {
212 0 => 1,
213 1 => 2,
214 2 => 4,
215 3 => 8,
216 _ => {
217 return Err(FlowSpecError::InvalidValueLength(
218 (operator_byte >> 4) & 0x03,
219 ))
220 }
221 };
222
223 if *offset + value_length > data.len() {
224 return Err(FlowSpecError::InsufficientData);
225 }
226
227 let value = read_value(&data[*offset..*offset + value_length]);
228 *offset += value_length;
229
230 let operator = NumericOperator::from_byte_and_value(operator_byte, value)?;
231 let is_end = operator.end_of_list;
232 operators.push(operator);
233
234 if is_end {
235 break;
236 }
237 }
238
239 Ok(operators)
240}
241
242fn parse_bitmask_operators(
244 data: &[u8],
245 offset: &mut usize,
246) -> Result<Vec<BitmaskOperator>, FlowSpecError> {
247 let mut operators = Vec::new();
248
249 loop {
250 if *offset >= data.len() {
251 return Err(FlowSpecError::InsufficientData);
252 }
253
254 let operator_byte = data[*offset];
255 *offset += 1;
256
257 let value_length = match (operator_byte >> 4) & 0x03 {
258 0 => 1,
259 1 => 2,
260 2 => 4,
261 3 => 8,
262 _ => {
263 return Err(FlowSpecError::InvalidValueLength(
264 (operator_byte >> 4) & 0x03,
265 ))
266 }
267 };
268
269 if *offset + value_length > data.len() {
270 return Err(FlowSpecError::InsufficientData);
271 }
272
273 let bitmask = read_value(&data[*offset..*offset + value_length]);
274 *offset += value_length;
275
276 let operator = BitmaskOperator::from_byte_and_value(operator_byte, bitmask)?;
277 let is_end = operator.end_of_list;
278 operators.push(operator);
279
280 if is_end {
281 break;
282 }
283 }
284
285 Ok(operators)
286}
287
288fn read_value(bytes: &[u8]) -> u64 {
290 let mut value = 0u64;
291 for &byte in bytes {
292 value = (value << 8) | byte as u64;
293 }
294 value
295}
296
297fn write_value(value: u64, length: usize, data: &mut Vec<u8>) {
299 for i in (0..length).rev() {
300 data.push((value >> (i * 8)) as u8);
301 }
302}
303
304fn parse_ip_protocol(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
306 let operators = parse_numeric_operators(data, offset)?;
307 Ok(FlowSpecComponent::IpProtocol(operators))
308}
309
310fn parse_port(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
311 let operators = parse_numeric_operators(data, offset)?;
312 Ok(FlowSpecComponent::Port(operators))
313}
314
315fn parse_destination_port(
316 data: &[u8],
317 offset: &mut usize,
318) -> Result<FlowSpecComponent, FlowSpecError> {
319 let operators = parse_numeric_operators(data, offset)?;
320 Ok(FlowSpecComponent::DestinationPort(operators))
321}
322
323fn parse_source_port(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
324 let operators = parse_numeric_operators(data, offset)?;
325 Ok(FlowSpecComponent::SourcePort(operators))
326}
327
328fn parse_icmp_type(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
329 let operators = parse_numeric_operators(data, offset)?;
330 Ok(FlowSpecComponent::IcmpType(operators))
331}
332
333fn parse_icmp_code(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
334 let operators = parse_numeric_operators(data, offset)?;
335 Ok(FlowSpecComponent::IcmpCode(operators))
336}
337
338fn parse_tcp_flags(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
339 let operators = parse_bitmask_operators(data, offset)?;
340 Ok(FlowSpecComponent::TcpFlags(operators))
341}
342
343fn parse_packet_length(
344 data: &[u8],
345 offset: &mut usize,
346) -> Result<FlowSpecComponent, FlowSpecError> {
347 let operators = parse_numeric_operators(data, offset)?;
348 Ok(FlowSpecComponent::PacketLength(operators))
349}
350
351fn parse_dscp(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
352 let operators = parse_numeric_operators(data, offset)?;
353 Ok(FlowSpecComponent::Dscp(operators))
354}
355
356fn parse_fragment(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
357 let operators = parse_bitmask_operators(data, offset)?;
358 Ok(FlowSpecComponent::Fragment(operators))
359}
360
361fn parse_flow_label(data: &[u8], offset: &mut usize) -> Result<FlowSpecComponent, FlowSpecError> {
362 let operators = parse_numeric_operators(data, offset)?;
363 Ok(FlowSpecComponent::FlowLabel(operators))
364}
365
366fn encode_prefix(prefix: &NetworkPrefix, data: &mut Vec<u8>) {
368 let prefix_len = prefix.prefix.prefix_len();
369 data.push(prefix_len);
370
371 let prefix_bytes = prefix_len.div_ceil(8);
372 let addr_bytes = match prefix.prefix.addr() {
373 std::net::IpAddr::V4(addr) => addr.octets().to_vec(),
374 std::net::IpAddr::V6(addr) => addr.octets().to_vec(),
375 };
376
377 data.extend(&addr_bytes[..prefix_bytes as usize]);
378}
379
380fn encode_ipv6_prefix(offset: u8, prefix: &NetworkPrefix, data: &mut Vec<u8>) {
381 data.push(prefix.prefix.prefix_len());
382 data.push(offset);
383
384 let prefix_bytes = prefix.prefix.prefix_len().div_ceil(8);
385 if let std::net::IpAddr::V6(addr) = prefix.prefix.addr() {
386 let addr_bytes = addr.octets();
387 data.extend(&addr_bytes[..prefix_bytes as usize]);
388 }
389}
390
391fn encode_numeric_operators(operators: &[NumericOperator], data: &mut Vec<u8>) {
392 for operator in operators {
393 data.push(operator.to_byte());
394 write_value(operator.value, operator.value_length as usize, data);
395 }
396}
397
398fn encode_bitmask_operators(operators: &[BitmaskOperator], data: &mut Vec<u8>) {
399 for operator in operators {
400 data.push(operator.to_byte());
401 write_value(operator.bitmask, operator.value_length as usize, data);
402 }
403}
404
405#[cfg(test)]
406mod tests {
407 use super::*;
408
409 #[test]
413 fn test_parse_prefix_component_oversized_len_no_panic() {
414 let mut data = vec![0xFF];
416 data.extend(std::iter::repeat_n(0u8, 32));
417 let mut offset = 0;
418 assert!(matches!(
419 parse_prefix_component(&data, &mut offset),
420 Err(FlowSpecError::InvalidPrefix)
421 ));
422 }
423
424 #[test]
425 fn test_length_encoding() {
426 let mut data = Vec::new();
428 encode_length(100, &mut data);
429 assert_eq!(data, vec![100]);
430
431 let mut offset = 0;
432 let parsed_len = parse_length(&data, &mut offset).unwrap();
433 assert_eq!(parsed_len, 100);
434 assert_eq!(offset, 1);
435
436 let mut data = Vec::new();
438 encode_length(1000, &mut data);
439 assert_eq!(data, vec![0xF3, 0xE8]); let mut offset = 0;
442 let parsed_len = parse_length(&data, &mut offset).unwrap();
443 assert_eq!(parsed_len, 1000);
444 assert_eq!(offset, 2);
445 }
446
447 #[test]
448 fn test_read_write_value() {
449 assert_eq!(read_value(&[0x25]), 0x25);
451
452 assert_eq!(read_value(&[0x01, 0xBB]), 443);
454
455 assert_eq!(read_value(&[0x00, 0x00, 0x00, 0x50]), 80);
457
458 let mut data = Vec::new();
460 write_value(443, 2, &mut data);
461 assert_eq!(data, vec![0x01, 0xBB]);
462 }
463
464 #[test]
465 fn test_simple_nlri_parsing() {
466 let data = vec![
468 0x08, 0x01, 0x18, 0xC0, 0x00, 0x02, 0x03, 0x81, 0x06, ];
476
477 let nlri = parse_flowspec_nlri(&data).unwrap();
478 assert_eq!(nlri.components.len(), 2);
479
480 match &nlri.components[0] {
481 FlowSpecComponent::DestinationPrefix(prefix) => {
482 assert_eq!(prefix.to_string(), "192.0.2.0/24");
483 }
484 _ => panic!("Expected destination prefix"),
485 }
486
487 match &nlri.components[1] {
488 FlowSpecComponent::IpProtocol(ops) => {
489 assert_eq!(ops.len(), 1);
490 assert_eq!(ops[0].value, 6);
491 assert!(ops[0].equal);
492 }
493 _ => panic!("Expected IP protocol"),
494 }
495 }
496
497 #[test]
498 fn test_nlri_round_trip() {
499 let original_nlri = FlowSpecNlri::new(vec![
500 FlowSpecComponent::DestinationPrefix(NetworkPrefix::from_str("192.0.2.0/24").unwrap()),
501 FlowSpecComponent::IpProtocol(vec![NumericOperator::equal_to(6)]),
502 FlowSpecComponent::DestinationPort(vec![NumericOperator::equal_to(80)]),
503 ]);
504
505 let encoded = encode_flowspec_nlri(&original_nlri);
506 let parsed_nlri = parse_flowspec_nlri(&encoded).unwrap();
507
508 assert_eq!(original_nlri, parsed_nlri);
509 }
510}