1use std::{
2 net::IpAddr,
3 pin::Pin,
4 task::{ready, Context, Poll},
5};
6
7use futures::{Sink, Stream};
8use smoltcp::wire::IpProtocol;
9use tokio::sync::mpsc::{channel, Receiver};
10use tokio_util::sync::PollSender;
11use tracing::{debug, trace};
12
13use crate::{
14 filter::{IpFilter, IpFilters},
15 packet::{AnyIpPktFrame, IpPacket},
16 runner::Runner,
17 tcp::TcpListener,
18 udp::UdpSocket,
19};
20
21pub struct StackBuilder {
22 enable_udp: bool,
23 enable_tcp: bool,
24 enable_icmp: bool,
25 stack_buffer_size: usize,
26 udp_buffer_size: usize,
27 tcp_buffer_size: usize,
28 tcp_recv_buffer_size: u32,
32 tcp_send_buffer_size: u32,
33 mtu: usize,
34 ip_filters: IpFilters<'static>,
35}
36
37impl Default for StackBuilder {
38 fn default() -> Self {
39 Self {
40 enable_udp: false,
41 enable_tcp: false,
42 enable_icmp: false,
43 stack_buffer_size: 1024,
44 udp_buffer_size: 512,
45 tcp_buffer_size: 512,
46 tcp_recv_buffer_size: 0x3FFF * 20,
53 tcp_send_buffer_size: 0x3FFF * 20,
54 mtu: 1504, ip_filters: IpFilters::with_non_broadcast(),
56 }
57 }
58}
59
60#[allow(unused)]
61impl StackBuilder {
62 pub fn enable_udp(mut self, enable: bool) -> Self {
63 self.enable_udp = enable;
64 self
65 }
66
67 pub fn enable_tcp(mut self, enable: bool) -> Self {
68 self.enable_tcp = enable;
69 self
70 }
71
72 pub fn enable_icmp(mut self, enable: bool) -> Self {
73 self.enable_icmp = enable;
74 self
75 }
76
77 pub fn stack_buffer_size(mut self, size: usize) -> Self {
78 self.stack_buffer_size = size;
79 self
80 }
81
82 pub fn udp_buffer_size(mut self, size: usize) -> Self {
83 self.udp_buffer_size = size;
84 self
85 }
86
87 pub fn tcp_buffer_size(mut self, size: usize) -> Self {
88 self.tcp_buffer_size = size;
89 self
90 }
91
92 pub fn tcp_recv_buffer_size(mut self, size: u32) -> Self {
98 self.tcp_recv_buffer_size = size;
99 self
100 }
101
102 pub fn tcp_send_buffer_size(mut self, size: u32) -> Self {
105 self.tcp_send_buffer_size = size;
106 self
107 }
108
109 pub fn set_ip_filters(mut self, filters: IpFilters<'static>) -> Self {
110 self.ip_filters = filters;
111 self
112 }
113
114 pub fn add_ip_filter(mut self, filter: IpFilter<'static>) -> Self {
115 self.ip_filters.add(filter);
116 self
117 }
118
119 pub fn add_ip_filter_fn<F>(mut self, filter: F) -> Self
120 where
121 F: Fn(&IpAddr, &IpAddr) -> bool + Send + Sync + 'static,
122 {
123 self.ip_filters.add_fn(filter);
124 self
125 }
126
127 pub fn mtu(mut self, mtu: usize) -> Self {
128 self.mtu = mtu;
129 self
130 }
131
132 #[allow(clippy::type_complexity)]
133 pub fn build(
134 self,
135 ) -> std::io::Result<(
136 Stack,
137 Option<Runner>,
138 Option<UdpSocket>,
139 Option<TcpListener>,
140 )> {
141 let (stack_tx, stack_rx) = channel(self.stack_buffer_size);
142
143 let (udp_tx, udp_rx) = if self.enable_udp {
144 let (udp_tx, udp_rx) = channel(self.udp_buffer_size);
145 (Some(PollSender::new(udp_tx)), Some(udp_rx))
146 } else {
147 (None, None)
148 };
149
150 let (tcp_tx, tcp_rx) = if self.enable_tcp {
151 let (tcp_tx, tcp_rx) = channel(self.tcp_buffer_size);
152 (Some(PollSender::new(tcp_tx)), Some(tcp_rx))
153 } else {
154 (None, None)
155 };
156
157 if self.enable_icmp && !self.enable_tcp {
160 use std::io::{Error, ErrorKind::InvalidInput};
161 return Err(Error::new(InvalidInput, "ICMP requires TCP"));
162 }
163 let icmp_tx = if self.enable_icmp {
164 tcp_tx.clone()
165 } else {
166 None
167 };
168
169 let udp_socket = udp_rx.map(|udp_rx| UdpSocket::new(udp_rx, stack_tx.clone()));
170
171 let (tcp_runner, tcp_listener) = if let Some(tcp_rx) = tcp_rx {
172 let (tcp_runner, tcp_listener) = TcpListener::new(
173 tcp_rx,
174 stack_tx,
175 self.mtu,
176 self.tcp_recv_buffer_size,
177 self.tcp_send_buffer_size,
178 )?;
179 (Some(tcp_runner), Some(tcp_listener))
180 } else {
181 (None, None)
182 };
183
184 let stack = Stack {
185 ip_filters: self.ip_filters,
186 stack_rx,
187 sink_buf: None,
188 udp_tx,
189 tcp_tx,
190 icmp_tx,
191 };
192
193 Ok((stack, tcp_runner, udp_socket, tcp_listener))
194 }
195}
196
197pub struct Stack {
198 ip_filters: IpFilters<'static>,
199 sink_buf: Option<(AnyIpPktFrame, IpProtocol)>,
200 udp_tx: Option<PollSender<AnyIpPktFrame>>,
201 tcp_tx: Option<PollSender<AnyIpPktFrame>>,
202 icmp_tx: Option<PollSender<AnyIpPktFrame>>,
203 stack_rx: Receiver<AnyIpPktFrame>,
204}
205
206impl Stack {
207 fn poll_send(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
208 let (item, proto) = match self.sink_buf.take() {
209 Some(val) => val,
210 None => return Poll::Ready(Ok(())),
211 };
212
213 let tx = match proto {
214 IpProtocol::Tcp => self.tcp_tx.as_mut(),
215 IpProtocol::Udp => self.udp_tx.as_mut(),
216 IpProtocol::Icmp | IpProtocol::Icmpv6 => self.icmp_tx.as_mut(),
217 _ => unreachable!(),
218 };
219
220 let Some(tx) = tx else {
221 return Poll::Ready(Ok(()));
222 };
223
224 match tx.poll_reserve(cx) {
225 Poll::Pending => {
226 self.sink_buf = Some((item, proto));
227 Poll::Pending
228 }
229 Poll::Ready(Err(_)) => Poll::Ready(Err(channel_closed_err("channel is closed"))),
230 Poll::Ready(Ok(_)) => match tx.send_item(item) {
231 Ok(()) => Poll::Ready(Ok(())),
232 Err(_) => Poll::Ready(Err(channel_closed_err("channel is closed"))),
233 },
234 }
235 }
236}
237
238impl Stream for Stack {
240 type Item = std::io::Result<AnyIpPktFrame>;
241
242 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
243 match self.stack_rx.poll_recv(cx) {
244 Poll::Ready(Some(pkt)) => Poll::Ready(Some(Ok(pkt))),
245 Poll::Ready(None) => Poll::Ready(None),
246 Poll::Pending => Poll::Pending,
247 }
248 }
249}
250
251impl Sink<AnyIpPktFrame> for Stack {
253 type Error = std::io::Error;
254
255 fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
256 if self.sink_buf.is_some() {
261 ready!(self.poll_send(cx))?;
262 }
263 Poll::Ready(Ok(()))
264 }
265
266 fn start_send(mut self: Pin<&mut Self>, item: AnyIpPktFrame) -> Result<(), Self::Error> {
267 if item.is_empty() {
268 return Ok(());
269 }
270
271 use std::io::{Error, ErrorKind::InvalidInput};
272 let packet = IpPacket::new_checked(item.as_slice())
273 .map_err(|err| Error::new(InvalidInput, format!("invalid IP packet: {err}")))?;
274
275 let src_ip = packet.src_addr();
276 let dst_ip = packet.dst_addr();
277
278 let addr_allowed = self.ip_filters.is_allowed(&src_ip, &dst_ip);
279 if !addr_allowed {
280 trace!("IP packet {src_ip} -> {dst_ip} (allowed? {addr_allowed}) throwing away",);
281 return Ok(());
282 }
283
284 let protocol = packet.protocol();
285 if matches!(
286 protocol,
287 IpProtocol::Tcp | IpProtocol::Udp | IpProtocol::Icmp | IpProtocol::Icmpv6
288 ) {
289 self.sink_buf.replace((item, protocol));
290 } else {
291 debug!("tun IP packet ignored (protocol: {:?})", protocol);
292 }
293
294 Ok(())
295 }
296
297 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
298 self.poll_send(cx)
299 }
300
301 fn poll_close(
302 mut self: Pin<&mut Self>,
303 _cx: &mut Context<'_>,
304 ) -> Poll<Result<(), Self::Error>> {
305 self.stack_rx.close();
306 Poll::Ready(Ok(()))
307 }
308}
309
310fn channel_closed_err<E>(err: E) -> std::io::Error
311where
312 E: Into<Box<dyn std::error::Error + Send + Sync>>,
313{
314 std::io::Error::new(std::io::ErrorKind::BrokenPipe, err)
315}
316
317#[cfg(test)]
318mod tcp_window_tests {
319 use super::*;
320
321 #[test]
328 fn tcp_window_defaults_to_historical_and_threads_overrides() {
329 let d = StackBuilder::default();
330 assert_eq!(d.tcp_recv_buffer_size, 0x3FFF * 20);
331 assert_eq!(d.tcp_send_buffer_size, 0x3FFF * 20);
332
333 let b = StackBuilder::default()
334 .tcp_recv_buffer_size(1 << 20)
335 .tcp_send_buffer_size(2 << 20);
336 assert_eq!(b.tcp_recv_buffer_size, 1 << 20);
337 assert_eq!(b.tcp_send_buffer_size, 2 << 20);
338 assert_eq!(b.tcp_buffer_size, 512);
340 }
341}