1use crate::ipv4_utils::ipv4_summarize_range;
2use ipnet::{IpNet, Ipv6Net};
3use std::cmp::{max, min};
4use std::collections::BTreeSet;
5use std::net::Ipv6Addr;
6
7pub fn find_overlaps(country_ips: &BTreeSet<IpNet>, as_ips: &BTreeSet<IpNet>) -> BTreeSet<IpNet> {
8 let country_agg = IpNet::aggregate(&country_ips.iter().copied().collect::<Vec<_>>());
10 let as_agg = IpNet::aggregate(&as_ips.iter().copied().collect::<Vec<_>>());
11
12 let (mut c_v4, mut c_v6) = split_ipv4_ipv6(&country_agg);
14 let (mut a_v4, mut a_v6) = split_ipv4_ipv6(&as_agg);
15
16 c_v4.sort_by_key(|(s, _)| *s);
17 a_v4.sort_by_key(|(s, _)| *s);
18 c_v6.sort_by_key(|(s, _)| *s);
19 a_v6.sort_by_key(|(s, _)| *s);
20
21 let o_v4 = overlap_ranges_v4(&c_v4, &a_v4);
22 let o_v6 = overlap_ranges_v6(&c_v6, &a_v6);
23
24 o_v4.into_iter().chain(o_v6).collect()
25}
26
27fn split_ipv4_ipv6(nets: &[IpNet]) -> (Vec<(u64, u64)>, Vec<(u128, u128)>) {
28 let mut v4 = Vec::new();
29 let mut v6 = Vec::new();
30
31 for net in nets {
32 match net {
33 IpNet::V4(n) => {
34 v4.push((
35 u32::from(n.network()) as u64,
36 u32::from(n.broadcast()) as u64,
37 ));
38 }
39 IpNet::V6(n) => {
40 v6.push((ipv6_to_u128(n.network()), ipv6_to_u128(n.broadcast())));
41 }
42 }
43 }
44 (v4, v6)
45}
46
47fn overlap_ranges_v4(country: &[(u64, u64)], aslist: &[(u64, u64)]) -> Vec<IpNet> {
48 let mut res = Vec::new();
49 let (mut i, mut j) = (0, 0);
50
51 while i < country.len() && j < aslist.len() {
52 let (c_s, c_e) = country[i];
53 let (a_s, a_e) = aslist[j];
54
55 let s = max(c_s, a_s);
56 let e = min(c_e, a_e);
57
58 if s <= e {
59 res.extend(ipv4_summarize_range(s, e));
60 }
61 if c_e < a_e {
62 i += 1;
63 } else {
64 j += 1;
65 }
66 }
67 res
68}
69
70fn overlap_ranges_v6(country: &[(u128, u128)], aslist: &[(u128, u128)]) -> Vec<IpNet> {
71 let mut res = Vec::new();
72 let (mut i, mut j) = (0, 0);
73
74 while i < country.len() && j < aslist.len() {
75 let (c_s, c_e) = country[i];
76 let (a_s, a_e) = aslist[j];
77
78 let s = max(c_s, a_s);
79 let e = min(c_e, a_e);
80
81 if s <= e {
82 res.extend(ipv6_summarize_range(s, e));
83 }
84 if c_e < a_e {
85 i += 1;
86 } else {
87 j += 1;
88 }
89 }
90 res
91}
92
93fn ipv6_summarize_range(start: u128, end: u128) -> Vec<IpNet> {
94 let mut cidrs = Vec::new();
95 let mut cur = start;
96
97 while cur <= end {
98 let max = largest_ipv6_block_in_overlap(cur, end);
99 if let Ok(net) = Ipv6Net::new(Ipv6Addr::from(cur), max) {
100 cidrs.push(IpNet::V6(net));
101 let step = 1u128 << (128 - max);
102 cur = cur.saturating_add(step);
103 } else {
104 break;
105 }
106 }
107
108 cidrs
109}
110
111fn ipv6_to_u128(addr: Ipv6Addr) -> u128 {
112 u128::from_be_bytes(addr.octets())
113}
114
115fn largest_ipv6_block_in_overlap(current: u128, end: u128) -> u8 {
116 let tz: u32 = current.trailing_zeros();
117 let span: u32 = ((end - current + 1).ilog2_128()) as u32;
118 let max: u32 = tz.min(span);
119 (128 - max) as u8
120}
121
122trait ILog2U128 {
123 fn ilog2_128(self) -> u32;
124}
125impl ILog2U128 for u128 {
126 fn ilog2_128(self) -> u32 {
127 if self == 0 {
128 0
129 } else {
130 127 - self.leading_zeros()
131 }
132 }
133}