Skip to main content

tuwunel_core/config/
net.rs

1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
2
3use either::{
4	Either,
5	Either::{Left, Right},
6};
7use ruma::ServerName;
8use serde::Deserialize;
9
10use crate::{Result, err, implement, utils::BoolExt};
11
12#[derive(Deserialize, Clone, Debug)]
13#[serde(transparent)]
14pub(super) struct ListeningPort {
15	#[serde(with = "either::serde_untagged")]
16	pub(super) ports: Either<u16, Vec<u16>>,
17}
18
19#[derive(Deserialize, Clone, Debug)]
20#[serde(transparent)]
21pub(super) struct ListeningAddr {
22	#[serde(with = "either::serde_untagged")]
23	pub(super) addrs: Either<IpAddr, Vec<IpAddr>>,
24}
25
26/// Interprets the configured Unix socket permission digits as an octal mode.
27///
28/// The returned value is suitable for applying to a newly created socket. An
29/// invalid octal digit produces a configuration error.
30#[implement(super::Config)]
31pub fn get_unix_socket_perms(&self) -> Result<u32> {
32	let octal_perms = self.unix_socket_perms.to_string();
33	let socket_perms = u32::from_str_radix(&octal_perms, 8)
34		.map_err(|_| err!(Config("unix_socket_perms", "failed to convert octal permissions")))?;
35
36	Ok(socket_perms)
37}
38
39/// Builds every configured TCP listener address.
40///
41/// The result is the Cartesian product of the configured hosts and ports. When
42/// neither TCP addresses nor a Unix socket are configured, loopback hosts
43/// apply.
44#[must_use]
45#[implement(super::Config)]
46pub fn get_bind_addrs(&self) -> Vec<SocketAddr> {
47	let mut addrs = Vec::with_capacity(
48		self.get_bind_hosts()
49			.len()
50			.saturating_mul(self.get_bind_ports().len()),
51	);
52	for host in &self.get_bind_hosts() {
53		for port in &self.get_bind_ports() {
54			addrs.push(SocketAddr::new(*host, *port));
55		}
56	}
57
58	addrs
59}
60
61#[implement(super::Config)]
62fn get_bind_hosts(&self) -> Vec<IpAddr> {
63	self.address.as_ref().map_or_else(
64		|| {
65			self.unix_socket_path
66				.is_none()
67				.then(|| vec![Ipv4Addr::LOCALHOST.into(), Ipv6Addr::LOCALHOST.into()])
68				.unwrap_or_default()
69		},
70		|address| match &address.addrs {
71			| Left(addr) => vec![*addr],
72			| Right(addrs) => addrs.clone(),
73		},
74	)
75}
76
77#[implement(super::Config)]
78fn get_bind_ports(&self) -> Vec<u16> {
79	match &self.port.ports {
80		| Left(port) => vec![*port],
81		| Right(ports) => ports.clone(),
82	}
83}
84
85/// Whether the addresses to bind come from the built-in default rather than
86/// the `address` option.
87///
88/// The default is a guess that both loopback families exist on the host, so
89/// one of them failing to bind is tolerable where a configured address is not.
90#[implement(super::Config)]
91#[inline]
92#[must_use]
93pub fn is_address_defaulted(&self) -> bool { self.address.is_none() }
94
95/// Determines whether a remote server name is forbidden.
96///
97/// The local server name is always permitted. Otherwise a deny-list match or an
98/// active allow-list miss forbids the destination.
99#[implement(super::Config)]
100#[must_use]
101pub fn is_forbidden_remote_server_name(&self, server_name: &ServerName) -> bool {
102	if server_name == self.server_name {
103		return false;
104	}
105
106	let deny_list_active = self
107		.forbidden_remote_server_names
108		.is_empty()
109		.is_false();
110
111	let allow_list_active = self
112		.allowed_remote_server_names_experimental
113		.is_empty()
114		.is_false();
115
116	if deny_list_active
117		&& self
118			.forbidden_remote_server_names
119			.is_match(server_name.host())
120	{
121		return true;
122	}
123
124	if allow_list_active
125		&& !self
126			.allowed_remote_server_names_experimental
127			.is_match(server_name.host())
128	{
129		return true;
130	}
131
132	false
133}