Skip to content

Commit c7b2e50

Browse files
authored
Add a Pool::insert_ip_net_any_port function. (#299)
* Add a `Pool::insert_ip_net_any_port` function. Add a function to `Pool` to allow inserting a network that can accept any port. * Add support for port ranges, and add some unit tests.
1 parent 58dd07c commit c7b2e50

File tree

3 files changed

+203
-13
lines changed

3 files changed

+203
-13
lines changed

cap-async-std/src/net/pool.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,36 @@ impl Pool {
2020
}
2121
}
2222

23+
/// Add a range of network addresses, accepting any port, to the pool.
24+
///
25+
/// Unlike `insert_ip_net`, this function grants access to any requested
26+
/// port.
27+
///
28+
/// # Ambient Authority
29+
///
30+
/// This function allows ambient access to any IP address.
31+
pub fn insert_ip_net_port_any(&mut self, ip_net: ipnet::IpNet, ambient_authority: AmbientAuthority) {
32+
self.cap.insert_ip_net_port_any(ip_net, ambient_authority)
33+
}
34+
35+
/// Add a range of network addresses, accepting a range of ports, to the pool.
36+
///
37+
/// This grants access to the port range starting at `ports_start` and,
38+
/// if `ports_end` is provided, ending before `ports_end`.
39+
///
40+
/// # Ambient Authority
41+
///
42+
/// This function allows ambient access to any IP address.
43+
pub fn insert_ip_net_port_range(
44+
&mut self,
45+
ip_net: ipnet::IpNet,
46+
ports_start: u16,
47+
ports_end: Option<u16>,
48+
ambient_authority: AmbientAuthority,
49+
) {
50+
self.cap.insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority)
51+
}
52+
2353
/// Add a range of network addresses with a specific port to the pool.
2454
///
2555
/// # Ambient Authority

cap-primitives/src/net/pool.rs

Lines changed: 138 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
use ambient_authority::AmbientAuthority;
1+
#[cfg(test)]
2+
use crate::ambient_authority;
3+
use crate::AmbientAuthority;
24
use ipnet::IpNet;
5+
#[cfg(test)]
6+
use std::str::FromStr;
37
use std::{io, net};
48

59
// TODO: Perhaps we should have our own version of `ToSocketAddrs` which
@@ -21,12 +25,27 @@ impl AddrSet {
2125
#[derive(Clone)]
2226
struct IpGrant {
2327
set: AddrSet,
24-
port: u16, // TODO: IANA port names, TODO: range
28+
ports_start: u16,
29+
ports_end: Option<u16>,
2530
}
2631

2732
impl IpGrant {
2833
fn contains(&self, addr: &net::SocketAddr) -> bool {
29-
self.set.contains(addr.ip()) && addr.port() == self.port
34+
if !self.set.contains(addr.ip()) {
35+
return false;
36+
}
37+
38+
let port = addr.port();
39+
if port < self.ports_start {
40+
return false;
41+
}
42+
if let Some(ports_end) = self.ports_end {
43+
if port >= ports_end {
44+
return false;
45+
}
46+
}
47+
48+
true
3049
}
3150
}
3251

@@ -46,25 +65,57 @@ impl Pool {
4665
Self { grants: Vec::new() }
4766
}
4867

49-
/// Add a range of network addresses with a specific port to the pool.
68+
/// Add a range of network addresses, accepting any port, to the pool.
5069
///
5170
/// # Ambient Authority
5271
///
5372
/// This function allows ambient access to any IP address.
54-
pub fn insert_ip_net(
73+
pub fn insert_ip_net_port_any(
5574
&mut self,
5675
ip_net: ipnet::IpNet,
57-
port: u16,
76+
ambient_authority: AmbientAuthority,
77+
) {
78+
self.insert_ip_net_port_range(ip_net, 0, None, ambient_authority)
79+
}
80+
81+
/// Add a range of network addresses, accepting a range of ports, to the pool.
82+
///
83+
/// This grants access to the port range starting at `ports_start` and,
84+
/// if `ports_end` is provided, ending before `ports_end`.
85+
///
86+
/// # Ambient Authority
87+
///
88+
/// This function allows ambient access to any IP address.
89+
pub fn insert_ip_net_port_range(
90+
&mut self,
91+
ip_net: ipnet::IpNet,
92+
ports_start: u16,
93+
ports_end: Option<u16>,
5894
ambient_authority: AmbientAuthority,
5995
) {
6096
let _ = ambient_authority;
6197

6298
self.grants.push(IpGrant {
6399
set: AddrSet::Net(ip_net),
64-
port,
100+
ports_start,
101+
ports_end,
65102
})
66103
}
67104

105+
/// Add a range of network addresses with a specific port to the pool.
106+
///
107+
/// # Ambient Authority
108+
///
109+
/// This function allows ambient access to any IP address.
110+
pub fn insert_ip_net(
111+
&mut self,
112+
ip_net: ipnet::IpNet,
113+
port: u16,
114+
ambient_authority: AmbientAuthority,
115+
) {
116+
self.insert_ip_net_port_range(ip_net, port, port.checked_add(1), ambient_authority)
117+
}
118+
68119
/// Add a specific [`net::SocketAddr`] to the pool.
69120
///
70121
/// # Ambient Authority
@@ -75,12 +126,7 @@ impl Pool {
75126
addr: net::SocketAddr,
76127
ambient_authority: AmbientAuthority,
77128
) {
78-
let _ = ambient_authority;
79-
80-
self.grants.push(IpGrant {
81-
set: AddrSet::Net(addr.ip().into()),
82-
port: addr.port(),
83-
})
129+
self.insert_ip_net(addr.ip().into(), addr.port(), ambient_authority)
84130
}
85131

86132
/// Check whether the given address is within the pool.
@@ -98,3 +144,82 @@ impl Pool {
98144

99145
/// An empty array of `SocketAddr`s.
100146
pub const NO_SOCKET_ADDRS: &[net::SocketAddr] = &[];
147+
148+
#[test]
149+
fn test_empty() {
150+
let p = Pool::new();
151+
152+
p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
153+
.unwrap_err();
154+
p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
155+
.unwrap_err();
156+
p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
157+
.unwrap_err();
158+
p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
159+
.unwrap_err();
160+
p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
161+
.unwrap_err();
162+
}
163+
164+
#[test]
165+
fn test_port_any() {
166+
let mut p = Pool::new();
167+
p.insert_ip_net_port_any(
168+
IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
169+
ambient_authority(),
170+
);
171+
172+
p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
173+
.unwrap();
174+
p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
175+
.unwrap();
176+
p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
177+
.unwrap();
178+
p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
179+
.unwrap();
180+
p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
181+
.unwrap();
182+
}
183+
184+
#[test]
185+
fn test_port_range() {
186+
let mut p = Pool::new();
187+
p.insert_ip_net_port_range(
188+
IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
189+
1024,
190+
Some(9000),
191+
ambient_authority(),
192+
);
193+
194+
p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
195+
.unwrap_err();
196+
p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
197+
.unwrap_err();
198+
p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
199+
.unwrap();
200+
p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
201+
.unwrap();
202+
p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
203+
.unwrap_err();
204+
}
205+
206+
#[test]
207+
fn test_port_one() {
208+
let mut p = Pool::new();
209+
p.insert_ip_net(
210+
IpNet::new(net::IpAddr::V6(net::Ipv6Addr::LOCALHOST), 48).unwrap(),
211+
8080,
212+
ambient_authority(),
213+
);
214+
215+
p.check_addr(&net::SocketAddr::from_str("[::1]:0").unwrap())
216+
.unwrap_err();
217+
p.check_addr(&net::SocketAddr::from_str("[::1]:1023").unwrap())
218+
.unwrap_err();
219+
p.check_addr(&net::SocketAddr::from_str("[::1]:1024").unwrap())
220+
.unwrap_err();
221+
p.check_addr(&net::SocketAddr::from_str("[::1]:8080").unwrap())
222+
.unwrap();
223+
p.check_addr(&net::SocketAddr::from_str("[::1]:65535").unwrap())
224+
.unwrap_err();
225+
}

cap-std/src/net/pool.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,41 @@ impl Pool {
2121
}
2222
}
2323

24+
/// Add a range of network addresses, accepting any port, to the pool.
25+
///
26+
/// Unlike `insert_ip_net`, this function grants access to any requested
27+
/// port.
28+
///
29+
/// # Ambient Authority
30+
///
31+
/// This function allows ambient access to any IP address.
32+
pub fn insert_ip_net_port_any(
33+
&mut self,
34+
ip_net: ipnet::IpNet,
35+
ambient_authority: AmbientAuthority,
36+
) {
37+
self.cap.insert_ip_net_port_any(ip_net, ambient_authority)
38+
}
39+
40+
/// Add a range of network addresses, accepting a range of ports, to the pool.
41+
///
42+
/// This grants access to the port range starting at `ports_start` and,
43+
/// if `ports_end` is provided, ending before `ports_end`.
44+
///
45+
/// # Ambient Authority
46+
///
47+
/// This function allows ambient access to any IP address.
48+
pub fn insert_ip_net_port_range(
49+
&mut self,
50+
ip_net: ipnet::IpNet,
51+
ports_start: u16,
52+
ports_end: Option<u16>,
53+
ambient_authority: AmbientAuthority,
54+
) {
55+
self.cap
56+
.insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority)
57+
}
58+
2459
/// Add a range of network addresses with a specific port to the pool.
2560
///
2661
/// # AmbientAuthority

0 commit comments

Comments
 (0)