cap_primitives/net/
pool.rs1#[cfg(test)]
2use crate::ambient_authority;
3use crate::net::pool::net::ToSocketAddrs;
4use crate::AmbientAuthority;
5use ipnet::IpNet;
6#[cfg(test)]
7use std::str::FromStr;
8use std::{io, net};
9
10#[derive(Clone)]
14enum AddrSet {
15 Net(IpNet),
16}
17
18impl AddrSet {
19 fn contains(&self, addr: net::IpAddr) -> bool {
20 match self {
21 Self::Net(ip_net) => ip_net.contains(&addr),
22 }
23 }
24}
25
26#[derive(Clone)]
27struct IpGrant {
28 set: AddrSet,
29 ports_start: u16,
30 ports_end: Option<u16>,
31}
32
33impl IpGrant {
34 fn contains(&self, addr: &net::SocketAddr) -> bool {
35 if !self.set.contains(addr.ip()) {
36 return false;
37 }
38
39 let port = addr.port();
40 if port < self.ports_start {
41 return false;
42 }
43 if let Some(ports_end) = self.ports_end {
44 if port >= ports_end {
45 return false;
46 }
47 }
48
49 true
50 }
51}
52
53#[derive(Clone, Default)]
69pub struct Pool {
70 grants: Vec<IpGrant>,
72}
73
74impl Pool {
75 pub fn new() -> Self {
77 Self { grants: Vec::new() }
78 }
79
80 pub fn insert<A: ToSocketAddrs>(
86 &mut self,
87 addrs: A,
88 ambient_authority: AmbientAuthority,
89 ) -> io::Result<()> {
90 for addr in addrs.to_socket_addrs()? {
91 self.insert_socket_addr(addr, ambient_authority);
92 }
93 Ok(())
94 }
95
96 pub fn insert_socket_addr(
102 &mut self,
103 addr: net::SocketAddr,
104 ambient_authority: AmbientAuthority,
105 ) {
106 self.insert_ip_net(addr.ip().into(), addr.port(), ambient_authority)
107 }
108
109 pub fn insert_ip_net_port_any(
115 &mut self,
116 ip_net: ipnet::IpNet,
117 ambient_authority: AmbientAuthority,
118 ) {
119 self.insert_ip_net_port_range(ip_net, 0, None, ambient_authority)
120 }
121
122 pub fn insert_ip_net_port_range(
132 &mut self,
133 ip_net: ipnet::IpNet,
134 ports_start: u16,
135 ports_end: Option<u16>,
136 ambient_authority: AmbientAuthority,
137 ) {
138 let _ = ambient_authority;
139
140 self.grants.push(IpGrant {
141 set: AddrSet::Net(ip_net),
142 ports_start,
143 ports_end,
144 })
145 }
146
147 pub fn insert_ip_net(
153 &mut self,
154 ip_net: ipnet::IpNet,
155 port: u16,
156 ambient_authority: AmbientAuthority,
157 ) {
158 self.insert_ip_net_port_range(ip_net, port, port.checked_add(1), ambient_authority)
159 }
160
161 pub fn check_addr(&self, addr: &net::SocketAddr) -> io::Result<()> {
163 if self.grants.iter().any(|grant| grant.contains(addr)) {
164 Ok(())
165 } else {
166 Err(io::Error::new(
167 io::ErrorKind::PermissionDenied,
168 "An address was outside the pool",
169 ))
170 }
171 }
172}
173
174pub const NO_SOCKET_ADDRS: &[net::SocketAddr] = &[];
176
177#[cold]
179pub fn no_socket_addrs() -> io::Error {
180 std::net::TcpListener::bind(NO_SOCKET_ADDRS).unwrap_err()
181}
182
183#[test]
184fn test_empty() {
185 let p = Pool::new();
186
187 p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
188 .unwrap_err();
189 p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
190 .unwrap_err();
191 p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
192 .unwrap_err();
193 p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
194 .unwrap_err();
195 p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
196 .unwrap_err();
197}
198
199#[test]
200fn test_port_any() {
201 let mut p = Pool::new();
202 p.insert_ip_net_port_any(
203 IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
204 ambient_authority(),
205 );
206
207 p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
208 .unwrap();
209 p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
210 .unwrap();
211 p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
212 .unwrap();
213 p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
214 .unwrap();
215 p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
216 .unwrap();
217}
218
219#[test]
220fn test_port_range() {
221 let mut p = Pool::new();
222 p.insert_ip_net_port_range(
223 IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
224 1024,
225 Some(9000),
226 ambient_authority(),
227 );
228
229 p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
230 .unwrap_err();
231 p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
232 .unwrap_err();
233 p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
234 .unwrap();
235 p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
236 .unwrap();
237 p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
238 .unwrap_err();
239}
240
241#[test]
242fn test_port_one() {
243 let mut p = Pool::new();
244 p.insert_ip_net(
245 IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
246 8080,
247 ambient_authority(),
248 );
249
250 p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
251 .unwrap_err();
252 p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
253 .unwrap_err();
254 p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
255 .unwrap_err();
256 p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
257 .unwrap();
258 p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
259 .unwrap_err();
260}
261
262#[test]
263fn test_addrs() {
264 let mut p = Pool::new();
265 match p.insert("example.com:80", ambient_authority()) {
266 Ok(()) => (),
267 Err(_) => return, }
269
270 p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
271 .unwrap_err();
272 p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
273 .unwrap_err();
274 p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
275 .unwrap_err();
276 p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
277 .unwrap_err();
278 p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
279 .unwrap_err();
280
281 for addr in "example.com:80".to_socket_addrs().unwrap() {
282 p.check_addr(&addr).unwrap();
283 }
284}