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