route_verification_bgp/cmp/
as_regex.rs

1use itertools::Itertools;
2use lazy_regex::Regex;
3
4use super::*;
5
6pub struct AsRegex<'a> {
7    pub c: &'a CheckFilter<'a>,
8    pub interpreter: Interpreter,
9    pub expr: &'a str,
10    pub report: AnyReportCase,
11}
12
13impl<'a> AsRegex<'a> {
14    pub fn check(&mut self, path: Vec<u32>) -> AnyReport {
15        let converted = match self.interpreter.run(self.expr) {
16            Ok(c) => c,
17            Err(HasTilde) => {
18                return self
19                    .c
20                    .skip_any_report(|| SkipAsRegexWithTilde(self.expr.into()))
21            }
22            Err(_) => return self.invalid_err(),
23        };
24        let converted_regex = match Regex::new(converted) {
25            Ok(c) => c,
26            Err(_) => return self.invalid_err(),
27        };
28        let replacements = path.iter().map(|n| self.asn_chars(*n)).collect::<Vec<_>>();
29        for chars in replacements.iter().multi_cartesian_product() {
30            let haystack: String = chars.into_iter().collect();
31            if converted_regex.is_match(&haystack) {
32                return None;
33            }
34        }
35        match mem::take(&mut self.report) {
36            BadAnyReport(_) => self.c.bad_any_report(|| MatchRegex(self.expr.into())),
37            non_bad => Some(non_bad),
38        }
39    }
40
41    /// chars corresponding to `asn`.
42    /// Unrecorded ASNs are assigned `¿` to avoid being matched.
43    pub fn asn_chars(&mut self, asn: u32) -> Vec<char> {
44        let mut result: Vec<_> = self.interpreter.get_asn(asn).into_iter().collect();
45        for (set, c) in self.interpreter.as_sets_with_char() {
46            match self.c.set_has_member(set, asn) {
47                Ok(true) => result.push(c),
48                Ok(false) => (),
49                Err(r) => self.report |= r.unwrap(),
50            }
51        }
52        if asn == self.c.accept_num {
53            result.push(self.interpreter.peer_as_char());
54        }
55        if result.is_empty() {
56            vec!['¿']
57        } else {
58            result
59        }
60    }
61
62    fn invalid_err(&self) -> AnyReport {
63        self.c
64            .bad_any_report(|| RpslInvalidAsRegex(self.expr.into()))
65    }
66}