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 mut path = Vec::with_capacity(count);
122
123 match as_length {
124 AsnLength::Bits16 => {
125 self.has_n_remaining(count * 2)?; for _ in 0..count {
127 path.push(Asn::new_16bit(self.read_u16()?));
128 }
129 }
130 AsnLength::Bits32 => {
131 self.has_n_remaining(count * 4)?; for _ in 0..count {
133 path.push(Asn::new_32bit(self.read_u32()?));
134 }
135 }
136 }
137
138 Ok(path)
139 }
140
141 fn read_afi(&mut self) -> Result<Afi, ParserError> {
142 Afi::try_from(self.read_u16()?).map_err(ParserError::from)
143 }
144
145 fn read_safi(&mut self) -> Result<Safi, ParserError> {
146 Safi::try_from(self.read_u8()?).map_err(ParserError::from)
147 }
148
149 fn read_nlri_prefix(
155 &mut self,
156 afi: &Afi,
157 add_path: bool,
158 ) -> Result<NetworkPrefix, ParserError> {
159 let data = self.chunk();
161 let (prefix, consumed) = try_parse_prefix(data, afi, add_path)?;
162 self.advance(consumed);
163 Ok(prefix)
164 }
165
166 fn read_n_bytes(&mut self, n_bytes: usize) -> Result<Vec<u8>, ParserError> {
167 self.has_n_remaining(n_bytes)?;
168 Ok(self.copy_to_bytes(n_bytes).into())
169 }
170
171 fn read_n_bytes_to_string(&mut self, n_bytes: usize) -> Result<String, ParserError> {
172 let buffer = self.read_n_bytes(n_bytes)?;
173 Ok(buffer
174 .into_iter()
175 .map(|x: u8| x as char)
176 .collect::<String>())
177 }
178}
179
180fn try_parse_prefix(
183 data: &[u8],
184 afi: &Afi,
185 add_path: bool,
186) -> Result<(NetworkPrefix, usize), ParserError> {
187 let mut pos = 0;
188
189 let path_id = if add_path {
191 if data.len() < pos + 4 {
192 return Err(ParserError::TruncatedMsg("truncated path_id".to_string()));
193 }
194 let id = u32::from_be_bytes([data[pos], data[pos + 1], data[pos + 2], data[pos + 3]]);
195 pos += 4;
196 Some(id)
197 } else {
198 None
199 };
200
201 if data.len() < pos + 1 {
203 return Err(ParserError::TruncatedMsg(
204 "truncated prefix length".to_string(),
205 ));
206 }
207 let bit_len = data[pos];
208 pos += 1;
209
210 let max_bit_len: u8 = match afi {
212 Afi::Ipv4 => 32,
213 Afi::Ipv6 => 128,
214 Afi::LinkState => 0,
215 };
216
217 if bit_len > max_bit_len {
218 return Err(ParserError::ParseError(format!(
219 "Invalid prefix length: {bit_len} (max {max_bit_len} for {afi:?})"
220 )));
221 }
222
223 let byte_len = (bit_len as usize).div_ceil(8);
225
226 let addr: IpAddr = match afi {
228 Afi::Ipv4 => {
229 if byte_len > 4 {
230 return Err(ParserError::ParseError(
231 "Invalid byte length for IPv4".to_string(),
232 ));
233 }
234 if data.len() < pos + byte_len {
235 return Err(ParserError::TruncatedMsg(
236 "truncated IPv4 prefix".to_string(),
237 ));
238 }
239 let mut buff = [0u8; 4];
240 buff[..byte_len].copy_from_slice(&data[pos..pos + byte_len]);
241 pos += byte_len;
242 IpAddr::V4(Ipv4Addr::from(buff))
243 }
244 Afi::Ipv6 => {
245 if byte_len > 16 {
246 return Err(ParserError::ParseError(
247 "Invalid byte length for IPv6".to_string(),
248 ));
249 }
250 if data.len() < pos + byte_len {
251 return Err(ParserError::TruncatedMsg(
252 "truncated IPv6 prefix".to_string(),
253 ));
254 }
255 let mut buff = [0u8; 16];
256 buff[..byte_len].copy_from_slice(&data[pos..pos + byte_len]);
257 pos += byte_len;
258 IpAddr::V6(Ipv6Addr::from(buff))
259 }
260 Afi::LinkState => {
261 pos += byte_len;
262 IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0))
263 }
264 };
265
266 let prefix = IpNet::new(addr, bit_len).map_err(|_| {
267 ParserError::ParseError(format!("Invalid network prefix length: {bit_len}"))
268 })?;
269
270 Ok((NetworkPrefix::new(prefix, path_id), pos))
271}
272
273pub fn parse_nlri_list(
274 mut input: Bytes,
275 add_path: bool,
276 afi: &Afi,
277) -> Result<Vec<NetworkPrefix>, ParserError> {
278 let mut prefixes = Vec::new();
279 let mut is_add_path = add_path;
280 let mut use_heuristic = false;
281
282 while input.remaining() > 0 {
283 let data = input.as_ref();
284
285 if !is_add_path && !data.is_empty() && data[0] == 0 {
287 debug!("NLRI: first byte is 0, treating as Add-Path format");
288 is_add_path = true;
289 use_heuristic = true;
290 }
291
292 let (prefix, consumed) = match try_parse_prefix(data, afi, is_add_path) {
294 Ok(result) => result,
295 Err(_) if use_heuristic => {
296 debug!(
298 "NLRI: Add-Path heuristic failed, retrying with add_path={}",
299 add_path
300 );
301 is_add_path = add_path;
302 use_heuristic = false;
303 try_parse_prefix(data, afi, add_path)?
304 }
305 Err(e) => return Err(e),
306 };
307
308 input.advance(consumed);
309 prefixes.push(prefix);
310 }
311
312 Ok(prefixes)
313}
314
315pub fn encode_asn(asn: &Asn, asn_len: &AsnLength) -> Bytes {
316 let mut bytes = BytesMut::new();
317 match asn_len {
318 AsnLength::Bits16 => bytes.put_u16(asn.into()),
319 AsnLength::Bits32 => {
320 bytes.put_u32(asn.into());
321 }
322 }
323 bytes.freeze()
324}
325
326pub fn encode_ipaddr(addr: &IpAddr) -> Vec<u8> {
327 match addr {
328 IpAddr::V4(addr) => addr.octets().to_vec(),
329 IpAddr::V6(addr) => addr.octets().to_vec(),
330 }
331}
332
333pub fn encode_nlri_prefixes(prefixes: &[NetworkPrefix]) -> Bytes {
334 let mut bytes = BytesMut::new();
335 for prefix in prefixes {
336 bytes.extend(prefix.encode());
337 }
338 bytes.freeze()
339}
340
341pub fn crc32(input: &str) -> String {
346 let input_bytes = input.as_bytes();
347 let mut table = [0u32; 256];
348 let polynomial = 0xedb88320u32;
349
350 for i in 0..256 {
351 let mut crc = i as u32;
352 for _ in 0..8 {
353 if crc & 1 == 1 {
354 crc = (crc >> 1) ^ polynomial;
355 } else {
356 crc >>= 1;
357 }
358 }
359 table[i as usize] = crc;
360 }
361
362 let mut crc = !0u32;
363 for byte in input_bytes.iter() {
364 let index = ((crc ^ (*byte as u32)) & 0xff) as usize;
365 crc = (crc >> 8) ^ table[index];
366 }
367
368 format!("{:08x}", !crc)
369}
370
371pub fn convert_timestamp(timestamp: f64) -> (u32, u32) {
393 let seconds = timestamp as u32;
394 let microseconds = ((timestamp - seconds as f64) * 1_000_000.0) as u32;
395 (seconds, microseconds)
396}
397
398#[derive(Debug, Clone)]
399pub struct ComparableRegex {
400 pattern: String,
401 regex: Regex,
402}
403
404impl PartialEq for ComparableRegex {
405 fn eq(&self, other: &Self) -> bool {
406 self.pattern == other.pattern
407 }
408}
409
410impl ComparableRegex {
411 pub fn new(pattern: &str) -> Result<Self, ParserError> {
412 let regex = match Regex::new(pattern) {
413 Ok(r) => r,
414 Err(_) => {
415 return Err(ParserError::FilterError(format!(
416 "Invalid regex pattern: {pattern}"
417 )))
418 }
419 };
420 Ok(ComparableRegex {
421 pattern: pattern.to_string(),
422 regex,
423 })
424 }
425
426 pub fn is_match<S: AsRef<str>>(&self, text: S) -> bool {
427 self.regex.is_match(text.as_ref())
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434 use bytes::Bytes;
435
436 #[test]
437 fn test_read_u8() {
438 let mut buf = Bytes::from_static(&[0x12]);
439 assert_eq!(buf.read_u8().unwrap(), 0x12);
440 }
441
442 #[test]
443 fn test_read_u16() {
444 let mut buf = Bytes::from_static(&[0x12, 0x34]);
445 assert_eq!(buf.read_u16().unwrap(), 0x1234);
446 }
447
448 #[test]
449 fn test_read_u32() {
450 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
451 assert_eq!(buf.read_u32().unwrap(), 0x12345678);
452 }
453
454 #[test]
455 fn test_read_u64() {
456 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]);
457 assert_eq!(buf.read_u64().unwrap(), 0x123456789ABCDEF0);
458 }
459
460 #[test]
461 fn test_read_ipv4_address() {
462 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01]);
463 assert_eq!(
464 buf.read_ipv4_address().unwrap(),
465 Ipv4Addr::new(192, 168, 1, 1)
466 );
467 }
468
469 #[test]
470 fn test_read_ipv6_address() {
471 let mut buf = Bytes::from_static(&[
472 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
473 0x73, 0x34,
474 ]);
475 assert_eq!(
476 buf.read_ipv6_address().unwrap(),
477 Ipv6Addr::new(0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334)
478 );
479 }
480
481 #[test]
482 fn test_read_address() {
483 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01]);
484 assert_eq!(
485 buf.read_address(&Afi::Ipv4).unwrap(),
486 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1))
487 );
488
489 let mut buf = Bytes::from_static(&[
490 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
491 0x73, 0x34,
492 ]);
493 assert_eq!(
494 buf.read_address(&Afi::Ipv6).unwrap(),
495 IpAddr::V6(Ipv6Addr::new(
496 0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334
497 ))
498 );
499
500 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01]);
501 assert!(buf.read_address(&Afi::Ipv4).is_err());
502
503 let mut buf = Bytes::from_static(&[
504 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
505 0x73,
506 ]);
507 assert!(buf.read_address(&Afi::Ipv6).is_err());
508 }
509
510 #[test]
511 fn test_read_asn() {
512 let mut buf = Bytes::from_static(&[0x00, 0x01]);
513 assert_eq!(buf.read_asn(AsnLength::Bits16).unwrap(), Asn::new_16bit(1));
514
515 let mut buf = Bytes::from_static(&[0x00, 0x00, 0x01, 0x00]);
516 assert_eq!(
517 buf.read_asn(AsnLength::Bits32).unwrap(),
518 Asn::new_32bit(256)
519 );
520 }
521
522 #[test]
523 fn read_asns() {
524 let mut buf = Bytes::from_static(&[0x00, 0x01, 0x00, 0x00]);
525 assert_eq!(
526 buf.read_asns(&AsnLength::Bits16, 2).unwrap(),
527 vec![Asn::new_16bit(1), Asn::new_16bit(0)]
528 );
529 }
530
531 #[test]
532 fn test_read_afi() {
533 let mut buf = Bytes::from_static(&[0x00, 0x01]);
534 assert_eq!(buf.read_afi().unwrap(), Afi::Ipv4);
535
536 let mut buf = Bytes::from_static(&[0x00, 0x02]);
537 assert_eq!(buf.read_afi().unwrap(), Afi::Ipv6);
538 }
539
540 #[test]
541 fn test_read_safi() {
542 let mut buf = Bytes::from_static(&[0x01]);
543 assert_eq!(buf.read_safi().unwrap(), Safi::Unicast);
544
545 let mut buf = Bytes::from_static(&[0x02]);
546 assert_eq!(buf.read_safi().unwrap(), Safi::Multicast);
547
548 let mut buf = Bytes::from_static(&[0x80]); assert_eq!(buf.read_safi().unwrap(), Safi::MplsVpn);
551
552 let mut buf = Bytes::from_static(&[0x81]); assert_eq!(buf.read_safi().unwrap(), Safi::MulticastVpn);
554 }
555
556 #[test]
557 fn test_has_n_remaining() {
558 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
559 assert!(buf.has_n_remaining(4).is_ok());
560 assert!(buf.has_n_remaining(5).is_err());
561
562 let _ = buf.read_u8().unwrap();
563 assert!(buf.has_n_remaining(3).is_ok());
564 assert!(buf.has_n_remaining(4).is_err());
565 }
566
567 #[test]
568 fn test_read_ipv4_prefix() {
569 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01, 0x18]);
570 assert_eq!(
571 buf.read_ipv4_prefix().unwrap(),
572 Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 1), 24).unwrap()
573 );
574
575 let mut buf = Bytes::from_static(&[0xC0, 0xA8, 0x01, 0x01, 0x21]);
577 assert!(buf.read_ipv4_prefix().is_err());
578 }
579
580 #[test]
581 fn test_read_ipv6_prefix() {
582 let mut buf = Bytes::from_static(&[
583 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
584 0x73, 0x34, 0x40,
585 ]);
586 assert_eq!(
587 buf.read_ipv6_prefix().unwrap(),
588 Ipv6Net::new(
589 Ipv6Addr::new(0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334),
590 64
591 )
592 .unwrap()
593 );
594
595 let mut buf = Bytes::from_static(&[
597 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
598 0x73, 0x34, 0x81,
599 ]);
600 assert!(buf.read_ipv6_prefix().is_err());
601 }
602
603 #[test]
604 fn test_read_n_bytes() {
605 let mut buf = Bytes::from_static(&[0x12, 0x34, 0x56, 0x78]);
606 assert_eq!(buf.read_n_bytes(4).unwrap(), vec![0x12, 0x34, 0x56, 0x78]);
607 }
608
609 #[test]
610 fn test_read_n_bytes_to_string() {
611 let mut buf = Bytes::from_static(&[0x48, 0x65, 0x6C, 0x6C, 0x6F]); assert_eq!(buf.read_n_bytes_to_string(5).unwrap(), "Hello");
613 }
614
615 #[test]
616 fn test_crc32() {
617 assert_eq!(crc32("Hello, World!"), "ec4ac3d0");
618 }
619
620 #[test]
621 fn test_read_nlri_prefix() {
622 let mut buf = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01]);
623 let expected = NetworkPrefix::new(
624 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
625 None,
626 );
627 assert_eq!(buf.read_nlri_prefix(&Afi::Ipv4, false).unwrap(), expected);
628
629 let mut buf = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01]);
630 let expected = NetworkPrefix::new(
631 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
632 Some(1),
633 );
634 assert_eq!(buf.read_nlri_prefix(&Afi::Ipv4, true).unwrap(), expected);
635 }
636
637 #[test]
638 fn test_read_nlri_prefix_length_validation() {
639 for invalid_len in [33u8, 255] {
641 let mut buf = Bytes::from(vec![invalid_len, 0xC0, 0xA8, 0x01]);
642 let result = buf.read_nlri_prefix(&Afi::Ipv4, false);
643 assert!(
644 result.is_err(),
645 "IPv4 prefix length {} should be rejected",
646 invalid_len
647 );
648 if let Err(ParserError::ParseError(msg)) = result {
649 assert!(msg.contains("Invalid prefix length"));
650 }
651 }
652
653 for invalid_len in [129u8, 255] {
655 let mut buf = Bytes::from(vec![invalid_len, 0x20, 0x01, 0x0D, 0xB8]);
656 let result = buf.read_nlri_prefix(&Afi::Ipv6, false);
657 assert!(
658 result.is_err(),
659 "IPv6 prefix length {} should be rejected",
660 invalid_len
661 );
662 if let Err(ParserError::ParseError(msg)) = result {
663 assert!(msg.contains("Invalid prefix length"));
664 }
665 }
666
667 for valid_len in [0u8, 1, 32] {
669 let mut buf = Bytes::from(vec![valid_len, 0x00, 0x00, 0x00, 0x00]);
671 let result = buf.read_nlri_prefix(&Afi::Ipv4, false);
672 assert!(
673 result.is_ok(),
674 "IPv4 prefix length {} should be valid",
675 valid_len
676 );
677 }
678
679 for valid_len in [0u8, 1, 64, 128] {
681 let buf_data: Vec<u8> = std::iter::once(valid_len)
683 .chain(std::iter::repeat_n(0x00, 16))
684 .collect();
685 let mut buf = Bytes::from(buf_data);
686 let result = buf.read_nlri_prefix(&Afi::Ipv6, false);
687 assert!(
688 result.is_ok(),
689 "IPv6 prefix length {} should be valid",
690 valid_len
691 );
692 }
693 }
694
695 #[test]
696 fn test_encode_asn() {
697 let asn = Asn::new_32bit(1);
698 let asn_len = AsnLength::Bits32;
699 let expected = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01]);
700 assert_eq!(encode_asn(&asn, &asn_len), expected);
701
702 let asn = Asn::new_16bit(1);
703 let asn_len = AsnLength::Bits16;
704 let expected = Bytes::from_static(&[0x00, 0x01]);
705 assert_eq!(encode_asn(&asn, &asn_len), expected);
706 }
707
708 #[test]
709 fn test_encode_ipaddr() {
710 let addr = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
711 let expected = vec![192, 168, 1, 1];
712 assert_eq!(encode_ipaddr(&addr), expected);
713
714 let addr = IpAddr::V6(Ipv6Addr::new(
715 0x2001, 0x0DB8, 0x85A3, 0x0000, 0x0000, 0x8A2E, 0x0370, 0x7334,
716 ));
717 let expected = vec![
718 0x20, 0x01, 0x0D, 0xB8, 0x85, 0xA3, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x2E, 0x03, 0x70,
719 0x73, 0x34,
720 ];
721 assert_eq!(encode_ipaddr(&addr), expected);
722 }
723
724 #[test]
725 fn test_encode_nlri_prefixes() {
726 let prefixes = vec![
727 NetworkPrefix::new(
728 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
729 None,
730 ),
731 NetworkPrefix::new(
732 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
733 None,
734 ),
735 ];
736 let expected = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01, 0x18, 0xC0, 0xA8, 0x02]);
737 assert_eq!(encode_nlri_prefixes(&prefixes), expected);
738
739 let prefixes = vec![
740 NetworkPrefix::new(
741 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
742 Some(1),
743 ),
744 NetworkPrefix::new(
745 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
746 Some(1),
747 ),
748 ];
749 let expected = Bytes::from_static(&[
750 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0,
751 0xA8, 0x02,
752 ]);
753 assert_eq!(encode_nlri_prefixes(&prefixes), expected);
754 }
755
756 #[test]
757 fn test_comparable_regex_functionality() {
758 let regex1 = ComparableRegex::new(r"\d+").unwrap();
760 let regex2 = ComparableRegex::new(r"\d+").unwrap();
761 let regex3 = ComparableRegex::new(r"\w+").unwrap();
762
763 assert_eq!(regex1.pattern, r"\d+");
765 assert_eq!(regex3.pattern, r"\w+");
766
767 assert_eq!(regex1, regex2);
769
770 assert_ne!(regex1, regex3);
772
773 assert!(regex1.regex.is_match("123"));
775 assert!(!regex1.regex.is_match("abc"));
776 }
777
778 #[test]
779 #[should_panic(expected = "Invalid regex pattern")]
780 fn test_comparable_regex_invalid_pattern_panic() {
781 ComparableRegex::new(r"(\d+").unwrap(); }
784
785 #[test]
786 fn test_parse_nlri_list() {
787 let input = Bytes::from_static(&[0x18, 0xC0, 0xA8, 0x01, 0x18, 0xC0, 0xA8, 0x02]);
789 let expected = vec![
790 NetworkPrefix::new(
791 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
792 None,
793 ),
794 NetworkPrefix::new(
795 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
796 None,
797 ),
798 ];
799 assert_eq!(parse_nlri_list(input, false, &Afi::Ipv4).unwrap(), expected);
800
801 let input = Bytes::from_static(&[
803 0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0xC0,
804 0xA8, 0x02,
805 ]);
806 let expected = vec![
807 NetworkPrefix::new(
808 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
809 Some(1),
810 ),
811 NetworkPrefix::new(
812 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 2, 0), 24).unwrap()),
813 Some(2),
814 ),
815 ];
816 assert_eq!(parse_nlri_list(input, true, &Afi::Ipv4).unwrap(), expected);
817
818 let input = Bytes::from_static(&[0x00, 0x00, 0x00, 0x01, 0x18, 0xC0, 0xA8, 0x01]);
820 let expected = vec![NetworkPrefix::new(
821 IpNet::V4(Ipv4Net::new(Ipv4Addr::new(192, 168, 1, 0), 24).unwrap()),
822 Some(1),
823 )];
824 assert_eq!(parse_nlri_list(input, false, &Afi::Ipv4).unwrap(), expected);
825 }
826
827 #[test]
828 fn test_convert_timestamp() {
829 let (seconds, microseconds) = convert_timestamp(1609459200.0);
831 assert_eq!(seconds, 1609459200);
832 assert_eq!(microseconds, 0);
833
834 let (seconds, microseconds) = convert_timestamp(1609459200.123456);
836 assert_eq!(seconds, 1609459200);
837 assert_eq!(microseconds, 123456);
838
839 let (seconds, microseconds) = convert_timestamp(1609459200.1234567);
841 assert_eq!(seconds, 1609459200);
842 assert_eq!(microseconds, 123456); }
844
845 #[test]
846 fn test_parse_nlri_list_add_path_heuristic() {
847 let input = Bytes::from(vec![
852 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x01, ]);
856
857 let result = parse_nlri_list(input, false, &Afi::Ipv4);
860 assert!(
861 result.is_ok(),
862 "Add-Path heuristic should parse successfully"
863 );
864
865 let prefixes = result.unwrap();
866 assert_eq!(prefixes.len(), 1);
867 assert_eq!(
868 prefixes[0].prefix.addr(),
869 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 0))
870 );
871 assert_eq!(prefixes[0].prefix.prefix_len(), 24);
872 assert_eq!(prefixes[0].path_id, Some(0));
873 }
874
875 #[test]
876 fn test_parse_nlri_list_non_addpath_with_zero_prefix() {
877 let input = Bytes::from(vec![
884 0x00, ]);
887
888 let result = parse_nlri_list(input, false, &Afi::Ipv4);
891
892 match result {
895 Ok(prefixes) => {
896 if !prefixes.is_empty() {
898 assert_eq!(prefixes[0].prefix.prefix_len(), 0);
899 }
900 }
901 Err(_) => {
902 }
905 }
906 }
907
908 #[test]
909 fn test_parse_nlri_list_multiple_prefixes_with_addpath() {
910 let input = Bytes::from(vec![
916 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0xA8, 0x02, ]);
925
926 let result = parse_nlri_list(input, false, &Afi::Ipv4);
928 assert!(result.is_ok(), "Should parse multiple Add-Path prefixes");
929
930 let prefixes = result.unwrap();
931 assert_eq!(prefixes.len(), 2, "Should have 2 prefixes");
932
933 assert_eq!(
935 prefixes[0].prefix.addr(),
936 IpAddr::V4(Ipv4Addr::new(192, 168, 1, 0))
937 );
938 assert_eq!(prefixes[0].prefix.prefix_len(), 24);
939 assert_eq!(prefixes[0].path_id, Some(0));
940
941 assert_eq!(
943 prefixes[1].prefix.addr(),
944 IpAddr::V4(Ipv4Addr::new(192, 168, 2, 0))
945 );
946 assert_eq!(prefixes[1].prefix.prefix_len(), 24);
947 assert_eq!(prefixes[1].path_id, Some(0));
948 }
949
950 #[test]
951 fn test_parse_nlri_list_ipv6_addpath() {
952 let input = Bytes::from(vec![
954 0x00, 0x00, 0x00, 0x01, 0x40, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
958 ]);
959
960 let result = parse_nlri_list(input, true, &Afi::Ipv6);
961 assert!(result.is_ok(), "Should parse IPv6 Add-Path prefix");
962
963 let prefixes = result.unwrap();
964 assert_eq!(prefixes.len(), 1);
965 assert_eq!(prefixes[0].prefix.prefix_len(), 64);
966 assert_eq!(prefixes[0].path_id, Some(1));
967 }
968
969 #[test]
970 fn test_parse_nlri_list_explicit_addpath_nonzero_path_id() {
971 let input = Bytes::from(vec![
973 0x00, 0x00, 0x00, 0xFF, 0x18, 0xC0, 0xA8, 0x01, ]);
977
978 let result = parse_nlri_list(input, true, &Afi::Ipv4);
979 assert!(result.is_ok());
980
981 let prefixes = result.unwrap();
982 assert_eq!(prefixes.len(), 1);
983 assert_eq!(prefixes[0].path_id, Some(255));
984 }
985
986 #[test]
987 fn test_parse_nlri_list_empty() {
988 let input = Bytes::from(vec![]);
990 let result = parse_nlri_list(input, false, &Afi::Ipv4);
991 assert!(result.is_ok());
992 assert!(result.unwrap().is_empty());
993 }
994
995 #[test]
996 fn test_parse_nlri_list_truncated_data() {
997 let input = Bytes::from(vec![
999 0x18, 0xC0, ]);
1002
1003 let result = parse_nlri_list(input, false, &Afi::Ipv4);
1004 assert!(result.is_err(), "Should error on truncated data");
1005 }
1006
1007 #[test]
1008 fn test_parse_nlri_list_heuristic_then_retry() {
1009 let input = Bytes::from(vec![
1017 0x00, ]);
1021
1022 let result = parse_nlri_list(input.clone(), false, &Afi::Ipv4);
1024 assert!(result.is_ok() || result.is_err());
1026 }
1028}