1use ipnet::{IpNet, Ipv4Net, Ipv6Net};
5use std::convert::TryFrom;
6use std::{
7 io,
8 net::{Ipv4Addr, Ipv6Addr},
9};
10
11use crate::error::ParserError;
12use crate::models::*;
13use crate::ParserError::TruncatedMsg;
14use bytes::{Buf, BufMut, Bytes, BytesMut};
15use log::debug;
16use regex::Regex;
17use std::net::IpAddr;
18
19impl ReadUtils for Bytes {}
20
21pub trait ReadUtils: Buf {
23 #[inline]
24 fn has_n_remaining(&self, n: usize) -> Result<(), ParserError> {
25 let remaining = self.remaining();
26 if remaining < n {
27 Err(TruncatedMsg(format!(
28 "not enough bytes to read. remaining: {remaining}, required: {n}"
29 )))
30 } else {
31 Ok(())
32 }
33 }
34
35 #[inline]
36 fn read_u8(&mut self) -> Result<u8, ParserError> {
37 self.has_n_remaining(1)?;
38 Ok(self.get_u8())
39 }
40
41 #[inline]
42 fn read_u16(&mut self) -> Result<u16, ParserError> {
43 self.has_n_remaining(2)?;
44 Ok(self.get_u16())
45 }
46
47 #[inline]
48 fn read_u32(&mut self) -> Result<u32, ParserError> {
49 self.has_n_remaining(4)?;
50 Ok(self.get_u32())
51 }
52
53 #[inline]
54 fn read_u64(&mut self) -> Result<u64, ParserError> {
55 self.has_n_remaining(8)?;
56 Ok(self.get_u64())
57 }
58
59 fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), ParserError> {
60 self.has_n_remaining(buf.len())?;
61 self.copy_to_slice(buf);
62 Ok(())
63 }
64
65 fn read_address(&mut self, afi: &Afi) -> io::Result<IpAddr> {
66 match afi {
67 Afi::Ipv4 => match self.read_ipv4_address() {
68 Ok(ip) => Ok(IpAddr::V4(ip)),
69 _ => Err(io::Error::other("Cannot parse IPv4 address")),
70 },
71 Afi::Ipv6 => match self.read_ipv6_address() {
72 Ok(ip) => Ok(IpAddr::V6(ip)),
73 _ => Err(io::Error::other("Cannot parse IPv6 address")),
74 },
75 Afi::LinkState => {
76 Ok(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)))
79 }
80 }
81 }
82
83 fn read_ipv4_address(&mut self) -> Result<Ipv4Addr, ParserError> {
84 let addr = self.read_u32()?;
85 Ok(Ipv4Addr::from(addr))
86 }
87
88 fn read_ipv6_address(&mut self) -> Result<Ipv6Addr, ParserError> {
89 self.has_n_remaining(16)?;
90 let buf = self.get_u128();
91 Ok(Ipv6Addr::from(buf))
92 }
93
94 fn read_ipv4_prefix(&mut self) -> Result<Ipv4Net, ParserError> {
95 let addr = self.read_ipv4_address()?;
96 let mask = self.read_u8()?;
97 match Ipv4Net::new(addr, mask) {
98 Ok(n) => Ok(n),
99 Err(_) => Err(io::Error::other("Invalid prefix mask").into()),
100 }
101 }
102
103 fn read_ipv6_prefix(&mut self) -> Result<Ipv6Net, ParserError> {
104 let addr = self.read_ipv6_address()?;
105 let mask = self.read_u8()?;
106 match Ipv6Net::new(addr, mask) {
107 Ok(n) => Ok(n),
108 Err(_) => Err(io::Error::other("Invalid prefix mask").into()),
109 }
110 }
111
112 #[inline]
113 fn read_asn(&mut self, as_length: AsnLength) -> Result<Asn, ParserError> {
114 match as_length {
115 AsnLength::Bits16 => self.read_u16().map(Asn::new_16bit),
116 AsnLength::Bits32 => self.read_u32().map(Asn::new_32bit),
117 }
118 }
119
120 fn read_asns(&mut self, as_length: &AsnLength, count: usize) -> Result<Vec<Asn>, ParserError> {
121 let width = match as_length {
126 AsnLength::Bits16 => 2,
127 AsnLength::Bits32 => 4,
128 };
129 let needed = count
130 .checked_mul(width)
131 .ok_or_else(|| TruncatedMsg("ASN count overflows buffer length".to_string()))?;
132 self.has_n_remaining(needed)?;
133
134 let mut path = Vec::with_capacity(count);
135 match as_length {
136 AsnLength::Bits16 => {
137 for _ in 0..count {
138 path.push(Asn::new_16bit(self.read_u16()?));
139 }
140 }
141 AsnLength::Bits32 => {
142 for _ in 0..count {
143 path.push(Asn::new_32bit(self.read_u32()?));
144 }
145 }
146 }
147
148 Ok(path)
149 }
150
151 fn read_afi(&mut self) -> Result<Afi, ParserError> {
152 Afi::try_from(self.read_u16()?).map_err(ParserError::from)
153 }
154
155 fn read_safi(&mut self) -> Result<Safi, ParserError> {
156 Safi::try_from(self.read_u8()?).map_err(ParserError::from)
157 }
158
159 fn read_nlri_prefix(
165 &mut self,
166 afi: &Afi,
167 add_path: bool,
168 ) -> Result<NetworkPrefix, ParserError> {
169 let data = self.chunk();
171 let (prefix, consumed) = try_parse_prefix(data, afi, add_path)?;
172 self.advance(consumed);
173 Ok(prefix)
174 }
175
176 fn read_n_bytes(&mut self, n_bytes: usize) -> Result<Vec<u8>, ParserError> {
177 self.has_n_remaining(n_bytes)?;
178 Ok(self.copy_to_bytes(n_bytes).into())
179 }
180
181 fn read_n_bytes_to_string(&mut self, n_bytes: usize) -> Result<String, ParserError> {
182 let buffer = self.read_n_bytes(n_bytes)?;
183 Ok(buffer
184 .into_iter()
185 .map(|x: u8| x as char)
186 .collect::<String>())
187 }
188}
189
190fn try_parse_prefix(
193 data: &[u8],
194 afi: &Afi,
195 add_path: bool,
196) -> Result<(NetworkPrefix, usize), ParserError> {
197 let mut pos = 0;
198
199 let path_id = if add_path {
201 if data.len() < pos + 4 {
202 return Err(ParserError::TruncatedMsg("truncated path_id".to_string()));
203 }
204 let id = u32::from_be_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]);
205 pos += 4;
206 Some(id)
207 } else {
208 None
209 };
210
211 if data.len() < pos + 1 {
213 return Err(ParserError::TruncatedMsg(
214 "truncated prefix length".to_string(),
215 ));
216 }
217 let bit_len = data[pos];
218 pos += 1;
219
220 let max_bit_len: u8 = match afi {
222 Afi::Ipv4 => 32,
223 Afi::Ipv6 => 128,
224 Afi::LinkState => 0,
225 };
226
227 if bit_len > max_bit_len {
228 return Err(ParserError::ParseError(format!(
229 "Invalid prefix length: {bit_len} (max {max_bit_len} for {afi:?})"
230 )));
231 }
232
233 let byte_len = (bit_len as usize).div_ceil(8);
235
236 let addr: IpAddr = match afi {
238 Afi::Ipv4 => {
239 if byte_len > 4 {
240 return Err(ParserError::ParseError(
241 "Invalid byte length for IPv4".to_string(),
242 ));
243 }
244 if data.len() < pos + byte_len {
245 return Err(ParserError::TruncatedMsg(
246 "truncated IPv4 prefix".to_string(),
247 ));
248 }
249 let mut buff = [0u8; 4];
250 buff[..byte_len].copy_from_slice(&data[pos..pos + byte_len]);
251 pos += byte_len;
252 IpAddr::V4(Ipv4Addr::from(buff))
253 }
254 Afi::Ipv6 => {
255 if byte_len > 16 {
256 return Err(ParserError::ParseError(
257 "Invalid byte length for IPv6".to_string(),
258 ));
259 }
260 if data.len() < pos + byte_len {
261 return Err(ParserError::TruncatedMsg(
262 "truncated IPv6 prefix".to_string(),
263 ));
264 }
265 let mut buff = [0u8; 16];
266 buff[..byte_len].copy_from_slice(&data[pos..pos + byte_len]);
267 pos += byte_len;
268 IpAddr::V6(Ipv6Addr::from(buff))
269 }
270 Afi::LinkState => {
271 pos += byte_len;
272 IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
273 }
274 };
275
276 let prefix = IpNet::new(addr, bit_len).map_err(|_| {
277 ParserError::ParseError(format!("Invalid network prefix length: {bit_len}"))
278 })?;
279
280 Ok((NetworkPrefix::new(prefix, path_id), pos))
281}
282
283pub fn parse_nlri_list(
284 mut input: Bytes,
285 add_path: bool,
286 afi: &Afi,
287) -> Result<Vec<NetworkPrefix>, ParserError> {
288 let mut prefixes = Vec::new();
289 let mut is_add_path = add_path;
290 let mut use_heuristic = false;
291
292 while input.remaining() > 0 {
293 let data = input.as_ref();
294
295 if !is_add_path && !data.is_empty() && data[0] == 0 {
297 debug!("NLRI: first byte is 0, treating as Add-Path format");
298 is_add_path = true;
299 use_heuristic = true;
300 }
301
302 let (prefix, consumed) = match try_parse_prefix(data, afi, is_add_path) {
304 Ok(result) => result,
305 Err(_) if use_heuristic => {
306 debug!(
308 "NLRI: Add-Path heuristic failed, retrying with add_path={}",
309 add_path
310 );
311 is_add_path = add_path;
312 use_heuristic = false;
313 try_parse_prefix(data, afi, add_path)?
314 }
315 Err(e) => return Err(e),
316 };
317
318 input.advance(consumed);
319 prefixes.push(prefix);
320 }
321
322 Ok(prefixes)
323}
324
325pub fn encode_asn(asn: &Asn, asn_len: &AsnLength) -> Bytes {
326 let mut bytes = BytesMut::new();
327 match asn_len {
328 AsnLength::Bits16 => bytes.put_u16(asn.into()),
329 AsnLength::Bits32 => {
330 bytes.put_u32(asn.into());
331 }
332 }
333 bytes.freeze()
334}
335
336pub fn encode_ipaddr(addr: &IpAddr) -> Vec<u8> {
337 match addr {
338 IpAddr::V4(addr) => addr.octets().to_vec(),
339 IpAddr::V6(addr) => addr.octets().to_vec(),
340 }
341}
342
343pub fn encode_nlri_prefixes(prefixes: &[NetworkPrefix]) -> Bytes {
344 let mut bytes = BytesMut::new();
345 for prefix in prefixes {
346 bytes.extend(prefix.encode());
347 }
348 bytes.freeze()
349}
350
351pub fn crc32(input: &str) -> String {
356 let input_bytes = input.as_bytes();
357 let mut table = [0u32; 256];
358 let polynomial = 0xedb88320u32;
359
360 for i in 0..256 {
361 let mut crc = i as u32;
362 for _ in 0..8 {
363 if crc & 1 == 1 {
364 crc = (crc >> 1) ^ polynomial;
365 } else {
366 crc >>= 1;
367 }
368 }
369 table[i as usize] = crc;
370 }
371
372 let mut crc = !0u32;
373 for byte in input_bytes.iter() {
374 let index = ((crc ^ (*byte as u32)) & 0xff) as usize;
375 crc = (crc >> 8) ^ table[index];
376 }
377
378 format!("{:08x}", !crc)
379}
380
381pub fn convert_timestamp(timestamp: f64) -> (u32, u32) {
403 let seconds = timestamp as u32;
404 let microseconds = ((timestamp - seconds as f64) * 1_000_000.0) as u32;
405 (seconds, microseconds)
406}
407
408#[derive(Debug, Clone)]
409pub struct ComparableRegex {
410 pattern: String,
411 regex: Regex,
412}
413
414impl PartialEq for ComparableRegex {
415 fn eq(&self, other: &Self) -> bool {
416 self.pattern == other.pattern
417 }
418}
419
420impl ComparableRegex {
421 pub fn new(pattern: &str) -> Result<Self, ParserError> {
422 let regex = match Regex::new(pattern) {
423 Ok(r) => r,
424 Err(_) => {
425 return Err(ParserError::FilterError(format!(
426 "Invalid regex pattern: {pattern}"
427 )))
428 }
429 };
430 Ok(ComparableRegex {
431 pattern: pattern.to_string(),
432 regex,
433 })
434 }
435
436 pub fn is_match<S: AsRef<str>>(&self, text: S) -> bool {
437 self.regex.is_match(text.as_ref())
438 }
439}
440
441#[cfg(test)]
442mod tests {
443 use super::*;
444 use bytes::Bytes;
445
446 #[test]
447 fn test_read_u8() {
448 let mut buf = Bytes::from_static(&[0x12]);
449 assert_eq!(buf.read_u8().unwrap(), 0x12);
450 }
451
452 #[test]
453 fn test_read_u16() {
454 let mut buf = Bytes::from_static(&[0x12, 0x34]);
455 assert_eq!(buf.read_u16().unwrap(), 0x1234);
456 }
457
458 #[test]
459 fn test_read_u32() {
460 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
461 assert_eq!(buf.read_u32().unwrap(), 0x12345678);
462 }
463
464 #[test]
465 fn test_read_u64() {
466 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]);
467 assert_eq!(buf.read_u64().unwrap(), 0x123456789ABCDEF0);
468 }
469
470 #[test]
471 fn test_read_ipv4_address() {
472 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01]);
473 assert_eq!(
474 buf.read_ipv4_address().unwrap(),
475 Ipv4Addr::new(192, 168, 1, 1)
476 );
477 }
478
479 #[test]
480 fn test_read_ipv6_address() {
481 let mut buf = Bytes::from_static(&[
482 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
483 0x73, 0x34,
484 ]);
485 assert_eq!(
486 buf.read_ipv6_address().unwrap(),
487 Ipv6Addr::new(0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334)
488 );
489 }
490
491 #[test]
492 fn test_read_address() {
493 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01]);
494 assert_eq!(
495 buf.read_address(&Afi::Ipv4).unwrap(),
496 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))
497 );
498
499 let mut buf = Bytes::from_static(&[
500 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
501 0x73, 0x34,
502 ]);
503 assert_eq!(
504 buf.read_address(&Afi::Ipv6).unwrap(),
505 IpAddr::V6(Ipv6Addr::new(
506 0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334
507 ))
508 );
509
510 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01]);
511 assert!(buf.read_address(&Afi::Ipv4).is_err());
512
513 let mut buf = Bytes::from_static(&[
514 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
515 0x73,
516 ]);
517 assert!(buf.read_address(&Afi::Ipv6).is_err());
518 }
519
520 #[test]
521 fn test_read_asn() {
522 let mut buf = Bytes::from_static(&[0x00, 0x01]);
523 assert_eq!(buf.read_asn(AsnLength::Bits16).unwrap(), Asn::new_16bit(1));
524
525 let mut buf = Bytes::from_static(&[0x00, 0x00, 0x01, 0x00]);
526 assert_eq!(
527 buf.read_asn(AsnLength::Bits32).unwrap(),
528 Asn::new_32bit(256)
529 );
530 }
531
532 #[test]
533 fn read_asns() {
534 let mut buf = Bytes::from_static(&[0x00, 0x01, 0x00, 0x00]);
535 assert_eq!(
536 buf.read_asns(&AsnLength::Bits16, 2).unwrap(),
537 vec![Asn::new_16bit(1), Asn::new_16bit(0)]
538 );
539 }
540
541 #[test]
542 fn test_read_afi() {
543 let mut buf = Bytes::from_static(&[0x00, 0x01]);
544 assert_eq!(buf.read_afi().unwrap(), Afi::Ipv4);
545
546 let mut buf = Bytes::from_static(&[0x00, 0x02]);
547 assert_eq!(buf.read_afi().unwrap(), Afi::Ipv6);
548 }
549
550 #[test]
551 fn test_read_safi() {
552 let mut buf = Bytes::from_static(&[0x01]);
553 assert_eq!(buf.read_safi().unwrap(), Safi::Unicast);
554
555 let mut buf = Bytes::from_static(&[0x02]);
556 assert_eq!(buf.read_safi().unwrap(), Safi::Multicast);
557
558 let mut buf = Bytes::from_static(&[0x80]); assert_eq!(buf.read_safi().unwrap(), Safi::MplsVpn);
561
562 let mut buf = Bytes::from_static(&[0x81]); assert_eq!(buf.read_safi().unwrap(), Safi::MulticastVpn);
564 }
565
566 #[test]
567 fn test_has_n_remaining() {
568 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
569 assert!(buf.has_n_remaining(4).is_ok());
570 assert!(buf.has_n_remaining(5).is_err());
571
572 let _ = buf.read_u8().unwrap();
573 assert!(buf.has_n_remaining(3).is_ok());
574 assert!(buf.has_n_remaining(4).is_err());
575 }
576
577 #[test]
578 fn test_read_ipv4_prefix() {
579 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01, 0x18]);
580 assert_eq!(
581 buf.read_ipv4_prefix().unwrap(),
582 Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 1), 24).unwrap()
583 );
584
585 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01, 0x21]);
587 assert!(buf.read_ipv4_prefix().is_err());
588 }
589
590 #[test]
591 fn test_read_ipv6_prefix() {
592 let mut buf = Bytes::from_static(&[
593 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
594 0x73, 0x34, 0x40,
595 ]);
596 assert_eq!(
597 buf.read_ipv6_prefix().unwrap(),
598 Ipv6Net::new(
599 Ipv6Addr::new(0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334),
600 64
601 )
602 .unwrap()
603 );
604
605 let mut buf = Bytes::from_static(&[
607 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
608 0x73, 0x34, 0x81,
609 ]);
610 assert!(buf.read_ipv6_prefix().is_err());
611 }
612
613 #[test]
614 fn test_read_n_bytes() {
615 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
616 assert_eq!(buf.read_n_bytes(4).unwrap(), vec![0x12, 0x34, 0x56, 0x78]);
617 }
618
619 #[test]
620 fn test_read_n_bytes_to_string() {
621 let mut buf = Bytes::from_static(&[0x48, 0x65, 0x6C, 0x6C, 0x6F]); assert_eq!(buf.read_n_bytes_to_string(5).unwrap(), "Hello");
623 }
624
625 #[test]
626 fn test_crc32() {
627 assert_eq!(crc32("Hello, World!"), "ec4ac3d0");
628 }
629
630 #[test]
631 fn test_read_nlri_prefix() {
632 let mut buf = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01]);
633 let expected = NetworkPrefix::new(
634 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
635 None,
636 );
637 assert_eq!(buf.read_nlri_prefix(&Afi::Ipv4, false).unwrap(), expected);
638
639 let mut buf = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01]);
640 let expected = NetworkPrefix::new(
641 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
642 Some(1),
643 );
644 assert_eq!(buf.read_nlri_prefix(&Afi::Ipv4, true).unwrap(), expected);
645 }
646
647 #[test]
648 fn test_read_nlri_prefix_length_validation() {
649 for invalid_len in [33u8, 255] {
651 let mut buf = Bytes::from(vec![invalid_len, 0xC0, 0xA8, 0x01]);
652 let result = buf.read_nlri_prefix(&Afi::Ipv4, false);
653 assert!(
654 result.is_err(),
655 "IPv4 prefix length {} should be rejected",
656 invalid_len
657 );
658 if let Err(ParserError::ParseError(msg)) = result {
659 assert!(msg.contains("Invalid prefix length"));
660 }
661 }
662
663 for invalid_len in [129u8, 255] {
665 let mut buf = Bytes::from(vec![invalid_len, 0x20, 0x01, 0x0D, 0xB8]);
666 let result = buf.read_nlri_prefix(&Afi::Ipv6, false);
667 assert!(
668 result.is_err(),
669 "IPv6 prefix length {} should be rejected",
670 invalid_len
671 );
672 if let Err(ParserError::ParseError(msg)) = result {
673 assert!(msg.contains("Invalid prefix length"));
674 }
675 }
676
677 for valid_len in [0u8, 1, 32] {
679 let mut buf = Bytes::from(vec![valid_len, 0x00, 0x00, 0x00, 0x00]);
681 let result = buf.read_nlri_prefix(&Afi::Ipv4, false);
682 assert!(
683 result.is_ok(),
684 "IPv4 prefix length {} should be valid",
685 valid_len
686 );
687 }
688
689 for valid_len in [0u8, 1, 64, 128] {
691 let buf_data: Vec<u8> = std::iter::once(valid_len)
693 .chain(std::iter::repeat_n(0x00, 16))
694 .collect();
695 let mut buf = Bytes::from(buf_data);
696 let result = buf.read_nlri_prefix(&Afi::Ipv6, false);
697 assert!(
698 result.is_ok(),
699 "IPv6 prefix length {} should be valid",
700 valid_len
701 );
702 }
703 }
704
705 #[test]
706 fn test_encode_asn() {
707 let asn = Asn::new_32bit(1);
708 let asn_len = AsnLength::Bits32;
709 let expected = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01]);
710 assert_eq!(encode_asn(&asn, &asn_len), expected);
711
712 let asn = Asn::new_16bit(1);
713 let asn_len = AsnLength::Bits16;
714 let expected = Bytes::from_static(&[0x00, 0x01]);
715 assert_eq!(encode_asn(&asn, &asn_len), expected);
716 }
717
718 #[test]
719 fn test_encode_ipaddr() {
720 let addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
721 let expected = vec![192, 168, 1, 1];
722 assert_eq!(encode_ipaddr(&addr), expected);
723
724 let addr = IpAddr::V6(Ipv6Addr::new(
725 0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334,
726 ));
727 let expected = vec![
728 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
729 0x73, 0x34,
730 ];
731 assert_eq!(encode_ipaddr(&addr), expected);
732 }
733
734 #[test]
735 fn test_encode_nlri_prefixes() {
736 let prefixes = vec![
737 NetworkPrefix::new(
738 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
739 None,
740 ),
741 NetworkPrefix::new(
742 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
743 None,
744 ),
745 ];
746 let expected = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01, 0x18, 0xC0, 0xA8, 0x02]);
747 assert_eq!(encode_nlri_prefixes(&prefixes), expected);
748
749 let prefixes = vec![
750 NetworkPrefix::new(
751 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
752 Some(1),
753 ),
754 NetworkPrefix::new(
755 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
756 Some(1),
757 ),
758 ];
759 let expected = Bytes::from_static(&[
760 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0,
761 0xA8, 0x02,
762 ]);
763 assert_eq!(encode_nlri_prefixes(&prefixes), expected);
764 }
765
766 #[test]
767 fn test_comparable_regex_functionality() {
768 let regex1 = ComparableRegex::new(r"\d+").unwrap();
770 let regex2 = ComparableRegex::new(r"\d+").unwrap();
771 let regex3 = ComparableRegex::new(r"\w+").unwrap();
772
773 assert_eq!(regex1.pattern, r"\d+");
775 assert_eq!(regex3.pattern, r"\w+");
776
777 assert_eq!(regex1, regex2);
779
780 assert_ne!(regex1, regex3);
782
783 assert!(regex1.regex.is_match("123"));
785 assert!(!regex1.regex.is_match("abc"));
786 }
787
788 #[test]
789 #[should_panic(expected = "Invalid regex pattern")]
790 fn test_comparable_regex_invalid_pattern_panic() {
791 ComparableRegex::new(r"(\d+").unwrap(); }
794
795 #[test]
796 fn test_parse_nlri_list() {
797 let input = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01, 0x18, 0xC0, 0xA8, 0x02]);
799 let expected = vec![
800 NetworkPrefix::new(
801 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
802 None,
803 ),
804 NetworkPrefix::new(
805 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
806 None,
807 ),
808 ];
809 assert_eq!(parse_nlri_list(input, false, &Afi::Ipv4).unwrap(), expected);
810
811 let input = Bytes::from_static(&[
813 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0xC0,
814 0xA8, 0x02,
815 ]);
816 let expected = vec![
817 NetworkPrefix::new(
818 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
819 Some(1),
820 ),
821 NetworkPrefix::new(
822 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
823 Some(2),
824 ),
825 ];
826 assert_eq!(parse_nlri_list(input, true, &Afi::Ipv4).unwrap(), expected);
827
828 let input = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01]);
830 let expected = vec![NetworkPrefix::new(
831 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
832 Some(1),
833 )];
834 assert_eq!(parse_nlri_list(input, false, &Afi::Ipv4).unwrap(), expected);
835 }
836
837 #[test]
838 fn test_convert_timestamp() {
839 let (seconds, microseconds) = convert_timestamp(1609459200.0);
841 assert_eq!(seconds, 1609459200);
842 assert_eq!(microseconds, 0);
843
844 let (seconds, microseconds) = convert_timestamp(1609459200.123456);
846 assert_eq!(seconds, 1609459200);
847 assert_eq!(microseconds, 123456);
848
849 let (seconds, microseconds) = convert_timestamp(1609459200.1234567);
851 assert_eq!(seconds, 1609459200);
852 assert_eq!(microseconds, 123456); }
854
855 #[test]
856 fn test_parse_nlri_list_add_path_heuristic() {
857 let input = Bytes::from(vec![
862 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x01, ]);
866
867 let result = parse_nlri_list(input, false, &Afi::Ipv4);
870 assert!(
871 result.is_ok(),
872 "Add-Path heuristic should parse successfully"
873 );
874
875 let prefixes = result.unwrap();
876 assert_eq!(prefixes.len(), 1);
877 assert_eq!(
878 prefixes[0].prefix.addr(),
879 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 0))
880 );
881 assert_eq!(prefixes[0].prefix.prefix_len(), 24);
882 assert_eq!(prefixes[0].path_id, Some(0));
883 }
884
885 #[test]
886 fn test_parse_nlri_list_non_addpath_with_zero_prefix() {
887 let input = Bytes::from(vec![
894 0x00, ]);
897
898 let result = parse_nlri_list(input, false, &Afi::Ipv4);
901
902 match result {
905 Ok(prefixes) => {
906 if !prefixes.is_empty() {
908 assert_eq!(prefixes[0].prefix.prefix_len(), 0);
909 }
910 }
911 Err(_) => {
912 }
915 }
916 }
917
918 #[test]
919 fn test_parse_nlri_list_multiple_prefixes_with_addpath() {
920 let input = Bytes::from(vec![
926 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x02, ]);
935
936 let result = parse_nlri_list(input, false, &Afi::Ipv4);
938 assert!(result.is_ok(), "Should parse multiple Add-Path prefixes");
939
940 let prefixes = result.unwrap();
941 assert_eq!(prefixes.len(), 2, "Should have 2 prefixes");
942
943 assert_eq!(
945 prefixes[0].prefix.addr(),
946 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 0))
947 );
948 assert_eq!(prefixes[0].prefix.prefix_len(), 24);
949 assert_eq!(prefixes[0].path_id, Some(0));
950
951 assert_eq!(
953 prefixes[1].prefix.addr(),
954 IpAddr::V4(Ipv4Addr::new(192, 168, 2, 0))
955 );
956 assert_eq!(prefixes[1].prefix.prefix_len(), 24);
957 assert_eq!(prefixes[1].path_id, Some(0));
958 }
959
960 #[test]
961 fn test_parse_nlri_list_ipv6_addpath() {
962 let input = Bytes::from(vec![
964 0x00, 0x00, 0x00, 0x01, 0x40, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
968 ]);
969
970 let result = parse_nlri_list(input, true, &Afi::Ipv6);
971 assert!(result.is_ok(), "Should parse IPv6 Add-Path prefix");
972
973 let prefixes = result.unwrap();
974 assert_eq!(prefixes.len(), 1);
975 assert_eq!(prefixes[0].prefix.prefix_len(), 64);
976 assert_eq!(prefixes[0].path_id, Some(1));
977 }
978
979 #[test]
980 fn test_parse_nlri_list_explicit_addpath_nonzero_path_id() {
981 let input = Bytes::from(vec![
983 0x00, 0x00, 0x00, 0xFF, 0x18, 0xC0, 0xA8, 0x01, ]);
987
988 let result = parse_nlri_list(input, true, &Afi::Ipv4);
989 assert!(result.is_ok());
990
991 let prefixes = result.unwrap();
992 assert_eq!(prefixes.len(), 1);
993 assert_eq!(prefixes[0].path_id, Some(255));
994 }
995
996 #[test]
997 fn test_parse_nlri_list_empty() {
998 let input = Bytes::from(vec![]);
1000 let result = parse_nlri_list(input, false, &Afi::Ipv4);
1001 assert!(result.is_ok());
1002 assert!(result.unwrap().is_empty());
1003 }
1004
1005 #[test]
1006 fn test_parse_nlri_list_truncated_data() {
1007 let input = Bytes::from(vec![
1009 0x18, 0xC0, ]);
1012
1013 let result = parse_nlri_list(input, false, &Afi::Ipv4);
1014 assert!(result.is_err(), "Should error on truncated data");
1015 }
1016
1017 #[test]
1018 fn test_parse_nlri_list_heuristic_then_retry() {
1019 let input = Bytes::from(vec![
1027 0x00, ]);
1031
1032 let result = parse_nlri_list(input.clone(), false, &Afi::Ipv4);
1034 assert!(result.is_ok() || result.is_err());
1036 }
1038}