tappers/
unix.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2//
3// Copyright (c) 2024 Nathaniel Bennett <me[at]nathanielbennett[dotcom]>
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! TUN/TAP interface for various other Unix systems.
12//!
13//!
14//!
15//!
16
17mod tap;
18mod tun;
19
20pub use tap::Tap;
21pub use tun::Tun;
22
23use std::net::IpAddr;
24#[cfg(not(target_os = "windows"))]
25use std::os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
26use std::{io, ptr};
27
28use crate::libc_extra::*;
29use crate::{AddAddress, AddressInfo, DeviceState, Interface};
30
31#[cfg(not(doc))]
32#[inline]
33pub(crate) fn ifreq_empty() -> ifreq {
34    ifreq {
35        ifr_name: [0; libc::IFNAMSIZ],
36        ifr_ifru: __c_anonymous_ifr_ifru {
37            ifru_data: ptr::null_mut(),
38        },
39    }
40}
41
42pub(crate) struct TunImpl {
43    tun: Tun,
44}
45
46impl TunImpl {
47    #[inline]
48    pub fn new() -> io::Result<Self> {
49        Ok(Self { tun: Tun::new()? })
50    }
51
52    #[inline]
53    pub fn new_named(if_name: Interface) -> io::Result<Self> {
54        Ok(Self {
55            tun: Tun::new_named(if_name)?,
56        })
57    }
58
59    #[inline]
60    pub fn addrs(&self) -> io::Result<Vec<AddressInfo>> {
61        self.tun.addrs()
62    }
63
64    #[inline]
65    pub fn add_addr<A: Into<AddAddress>>(&self, req: A) -> io::Result<()> {
66        self.tun.add_addr(req)
67    }
68
69    #[inline]
70    pub fn remove_addr(&self, addr: IpAddr) -> io::Result<()> {
71        self.tun.remove_addr(addr)
72    }
73
74    #[inline]
75    pub fn name(&self) -> io::Result<Interface> {
76        self.tun.name()
77    }
78
79    #[inline]
80    pub fn set_state(&mut self, state: DeviceState) -> io::Result<()> {
81        self.tun.set_state(state)
82    }
83
84    #[inline]
85    pub fn mtu(&self) -> io::Result<usize> {
86        self.tun.mtu()
87    }
88
89    #[inline]
90    pub fn set_nonblocking(&mut self, nonblocking: bool) -> io::Result<()> {
91        self.tun.set_nonblocking(nonblocking)
92    }
93
94    #[inline]
95    pub fn nonblocking(&self) -> io::Result<bool> {
96        self.tun.nonblocking()
97    }
98
99    /// Sends a packet out over the TUN device.
100    #[inline]
101    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
102        self.tun.send(buf)
103    }
104
105    #[inline]
106    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
107        self.tun.recv(buf)
108    }
109}
110
111#[cfg(not(target_os = "windows"))]
112impl AsRawFd for TunImpl {
113    fn as_raw_fd(&self) -> RawFd {
114        self.tun.as_raw_fd()
115    }
116}
117
118#[cfg(not(target_os = "windows"))]
119impl AsFd for TunImpl {
120    fn as_fd(&self) -> BorrowedFd {
121        self.tun.as_fd()
122    }
123}
124
125pub(crate) struct TapImpl {
126    tap: Tap,
127}
128
129impl TapImpl {
130    #[inline]
131    pub fn new() -> io::Result<Self> {
132        Ok(Self { tap: Tap::new()? })
133    }
134
135    #[inline]
136    pub fn new_named(if_name: Interface) -> io::Result<Self> {
137        Ok(Self {
138            tap: Tap::new_named(if_name)?,
139        })
140    }
141
142    #[inline]
143    pub fn addrs(&self) -> io::Result<Vec<AddressInfo>> {
144        self.tap.addrs()
145    }
146
147    #[inline]
148    pub fn add_addr<A: Into<AddAddress>>(&self, req: A) -> io::Result<()> {
149        self.tap.add_addr(req)
150    }
151
152    #[inline]
153    pub fn remove_addr(&self, addr: IpAddr) -> io::Result<()> {
154        self.tap.remove_addr(addr)
155    }
156
157    #[inline]
158    pub fn name(&self) -> io::Result<Interface> {
159        self.tap.name()
160    }
161
162    #[inline]
163    pub fn set_state(&mut self, state: DeviceState) -> io::Result<()> {
164        self.tap.set_state(state)
165    }
166
167    #[inline]
168    pub fn mtu(&self) -> io::Result<usize> {
169        self.tap.mtu()
170    }
171
172    #[inline]
173    pub fn set_nonblocking(&mut self, nonblocking: bool) -> io::Result<()> {
174        self.tap.set_nonblocking(nonblocking)
175    }
176
177    #[inline]
178    pub fn nonblocking(&self) -> io::Result<bool> {
179        self.tap.nonblocking()
180    }
181
182    #[inline]
183    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
184        self.tap.send(buf)
185    }
186
187    #[inline]
188    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
189        self.tap.recv(buf)
190    }
191}
192
193#[cfg(not(target_os = "windows"))]
194impl AsFd for TapImpl {
195    fn as_fd(&self) -> BorrowedFd {
196        self.tap.as_fd()
197    }
198}
199
200#[cfg(not(target_os = "windows"))]
201impl AsRawFd for TapImpl {
202    fn as_raw_fd(&self) -> RawFd {
203        self.tap.as_raw_fd()
204    }
205}