1use libc::{
16 self, c_char, c_short, ifreq, AF_INET, IFF_MULTI_QUEUE, IFF_NAPI, IFF_NO_PI, IFF_RUNNING,
17 IFF_TAP, IFF_TUN, IFF_UP, IFF_VNET_HDR, IFNAMSIZ, O_RDWR, SOCK_DGRAM,
18};
19use std::{
20 ffi::{CStr, CString},
21 io::{Read, Write},
22 mem,
23 net::IpAddr,
24 os::unix::io::{AsRawFd, IntoRawFd, RawFd},
25 ptr,
26};
27
28use crate::{
29 configuration::{Configuration, Layer},
30 device::AbstractDevice,
31 error::{Error, Result},
32 platform::linux::sys::*,
33 platform::posix::{self, ipaddr_to_sockaddr, sockaddr_union, Fd, Tun},
34};
35
36const OVERWRITE_SIZE: usize = std::mem::size_of::<libc::__c_anonymous_ifr_ifru>();
37
38pub struct Device {
40 tun_name: String,
41 tun: Tun,
42 ctl: Fd,
43}
44
45impl AsRef<dyn AbstractDevice + 'static> for Device {
46 fn as_ref(&self) -> &(dyn AbstractDevice + 'static) {
47 self
48 }
49}
50
51impl AsMut<dyn AbstractDevice + 'static> for Device {
52 fn as_mut(&mut self) -> &mut (dyn AbstractDevice + 'static) {
53 self
54 }
55}
56
57impl Device {
58 pub fn new(config: &Configuration) -> Result<Self> {
60 if let Some(fd) = config.raw_fd {
61 let close_fd_on_drop = config.close_fd_on_drop.unwrap_or(true);
62 let tun_fd = Fd::new(fd, close_fd_on_drop)?;
63 let mtu = config.mtu.unwrap_or(crate::DEFAULT_MTU);
64 let packet_information = config.platform_config.packet_information;
65 let tun_name = config.tun_name.clone().unwrap_or_else(|| "".into());
66 let ctl = Fd::new(unsafe { libc::socket(AF_INET, SOCK_DGRAM, 0) }, true)?;
67 return Ok(Device {
68 tun: Tun::new(tun_fd, mtu, packet_information),
69 tun_name,
70 ctl,
71 });
72 }
73
74 let mut device = unsafe {
75 let dev_name = match config.tun_name.as_ref() {
76 Some(tun_name) => {
77 let tun_name = CString::new(tun_name.clone())?;
78
79 if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
80 return Err(Error::NameTooLong);
81 }
82
83 Some(tun_name)
84 }
85
86 None => None,
87 };
88
89 let mut req: ifreq = mem::zeroed();
90
91 if let Some(dev_name) = dev_name.as_ref() {
92 ptr::copy_nonoverlapping(
93 dev_name.as_ptr() as *const c_char,
94 req.ifr_name.as_mut_ptr(),
95 dev_name.as_bytes_with_nul().len(),
96 );
97 }
98
99 let device_type: c_short = config.layer.unwrap_or(Layer::L3).into();
100
101 let queues_num = config.queues.unwrap_or(1);
102 if queues_num != 1 {
103 return Err(Error::InvalidQueuesNumber);
104 }
105
106 let iff_no_pi = IFF_NO_PI as c_short;
107 let iff_multi_queue = IFF_MULTI_QUEUE as c_short;
108 let iff_napi = IFF_NAPI as c_short;
109 let iff_vnet_hdr = IFF_VNET_HDR as c_short;
110 let packet_information = config.platform_config.packet_information;
111 let napi = config.platform_config.napi;
112 let vnet_hdr = config.platform_config.vnet_hdr;
113 req.ifr_ifru.ifru_flags = device_type
114 | if packet_information { 0 } else { iff_no_pi }
115 | if napi { iff_napi } else { 0 }
116 | if vnet_hdr { iff_vnet_hdr } else { 0 }
117 | if queues_num > 1 { iff_multi_queue } else { 0 };
118
119 let tun_fd = {
120 let fd = libc::open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR);
121 let tun_fd = Fd::new(fd, true).map_err(|_| std::io::Error::last_os_error())?;
122
123 if let Err(err) = tunsetiff(tun_fd.inner, &mut req as *mut _ as *mut _) {
124 return Err(std::io::Error::from(err).into());
125 }
126
127 tun_fd
128 };
129
130 let mtu = config.mtu.unwrap_or(crate::DEFAULT_MTU);
131
132 let ctl = Fd::new(libc::socket(AF_INET, SOCK_DGRAM, 0), true)?;
133
134 let tun_name = CStr::from_ptr(req.ifr_name.as_ptr())
135 .to_string_lossy()
136 .to_string();
137 Device {
138 tun_name,
139 tun: Tun::new(tun_fd, mtu, packet_information),
140 ctl,
141 }
142 };
143
144 if config.platform_config.ensure_root_privileges {
145 device.configure(config)?;
146 }
147
148 Ok(device)
149 }
150
151 unsafe fn request(&self) -> ifreq {
153 let mut req: ifreq = mem::zeroed();
154 ptr::copy_nonoverlapping(
155 self.tun_name.as_ptr() as *const c_char,
156 req.ifr_name.as_mut_ptr(),
157 self.tun_name.len(),
158 );
159
160 req
161 }
162
163 pub fn persist(&mut self) -> Result<()> {
165 unsafe {
166 if let Err(err) = tunsetpersist(self.as_raw_fd(), &1) {
167 Err(std::io::Error::from(err).into())
168 } else {
169 Ok(())
170 }
171 }
172 }
173
174 pub fn user(&mut self, value: i32) -> Result<()> {
176 unsafe {
177 if let Err(err) = tunsetowner(self.as_raw_fd(), &value) {
178 Err(std::io::Error::from(err).into())
179 } else {
180 Ok(())
181 }
182 }
183 }
184
185 pub fn group(&mut self, value: i32) -> Result<()> {
187 unsafe {
188 if let Err(err) = tunsetgroup(self.as_raw_fd(), &value) {
189 Err(std::io::Error::from(err).into())
190 } else {
191 Ok(())
192 }
193 }
194 }
195
196 pub fn split(self) -> (posix::Reader, posix::Writer) {
198 (self.tun.reader, self.tun.writer)
199 }
200
201 pub fn set_nonblock(&self) -> std::io::Result<()> {
203 self.tun.set_nonblock()
204 }
205
206 pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
208 self.tun.recv(buf)
209 }
210
211 pub fn send(&self, buf: &[u8]) -> std::io::Result<usize> {
213 self.tun.send(buf)
214 }
215}
216
217impl Read for Device {
218 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
219 self.tun.read(buf)
220 }
221
222 fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
223 self.tun.read_vectored(bufs)
224 }
225}
226
227impl Write for Device {
228 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
229 self.tun.write(buf)
230 }
231
232 fn flush(&mut self) -> std::io::Result<()> {
233 self.tun.flush()
234 }
235
236 fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
237 self.tun.write_vectored(bufs)
238 }
239}
240
241impl AbstractDevice for Device {
242 fn tun_index(&self) -> Result<i32> {
243 let name = self.tun_name()?;
244 Ok(posix::tun_name_to_index(name)? as i32)
245 }
246
247 fn tun_name(&self) -> Result<String> {
248 Ok(self.tun_name.clone())
249 }
250
251 fn set_tun_name(&mut self, value: &str) -> Result<()> {
252 unsafe {
253 let tun_name = CString::new(value)?;
254
255 if tun_name.as_bytes_with_nul().len() > IFNAMSIZ {
256 return Err(Error::NameTooLong);
257 }
258
259 let mut req = self.request();
260 ptr::copy_nonoverlapping(
261 tun_name.as_ptr() as *const c_char,
262 req.ifr_ifru.ifru_newname.as_mut_ptr(),
263 value.len(),
264 );
265
266 if let Err(err) = siocsifname(self.ctl.as_raw_fd(), &req) {
267 return Err(std::io::Error::from(err).into());
268 }
269
270 self.tun_name = value.into();
271
272 Ok(())
273 }
274 }
275
276 fn enabled(&mut self, value: bool) -> Result<()> {
277 unsafe {
278 let mut req = self.request();
279
280 if let Err(err) = siocgifflags(self.ctl.as_raw_fd(), &mut req) {
281 return Err(std::io::Error::from(err).into());
282 }
283
284 if value {
285 req.ifr_ifru.ifru_flags |= (IFF_UP | IFF_RUNNING) as c_short;
286 } else {
287 req.ifr_ifru.ifru_flags &= !(IFF_UP as c_short);
288 }
289
290 if let Err(err) = siocsifflags(self.ctl.as_raw_fd(), &req) {
291 return Err(std::io::Error::from(err).into());
292 }
293
294 Ok(())
295 }
296 }
297
298 fn address(&self) -> Result<IpAddr> {
299 unsafe {
300 let mut req = self.request();
301 if let Err(err) = siocgifaddr(self.ctl.as_raw_fd(), &mut req) {
302 return Err(std::io::Error::from(err).into());
303 }
304 let sa = sockaddr_union::from(req.ifr_ifru.ifru_addr);
305 Ok(std::net::SocketAddr::try_from(sa)?.ip())
306 }
307 }
308
309 fn set_address(&mut self, value: IpAddr) -> Result<()> {
310 unsafe {
311 let mut req = self.request();
312 ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_addr, OVERWRITE_SIZE);
313 if let Err(err) = siocsifaddr(self.ctl.as_raw_fd(), &req) {
314 return Err(std::io::Error::from(err).into());
315 }
316 Ok(())
317 }
318 }
319
320 fn destination(&self) -> Result<IpAddr> {
321 unsafe {
322 let mut req = self.request();
323 if let Err(err) = siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) {
324 return Err(std::io::Error::from(err).into());
325 }
326 let sa = sockaddr_union::from(req.ifr_ifru.ifru_dstaddr);
327 Ok(std::net::SocketAddr::try_from(sa)?.ip())
328 }
329 }
330
331 fn set_destination(&mut self, value: IpAddr) -> Result<()> {
332 unsafe {
333 let mut req = self.request();
334 ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_dstaddr, OVERWRITE_SIZE);
335 if let Err(err) = siocsifdstaddr(self.ctl.as_raw_fd(), &req) {
336 return Err(std::io::Error::from(err).into());
337 }
338 Ok(())
339 }
340 }
341
342 fn broadcast(&self) -> Result<IpAddr> {
343 unsafe {
344 let mut req = self.request();
345 if let Err(err) = siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) {
346 return Err(std::io::Error::from(err).into());
347 }
348 let sa = sockaddr_union::from(req.ifr_ifru.ifru_broadaddr);
349 Ok(std::net::SocketAddr::try_from(sa)?.ip())
350 }
351 }
352
353 fn set_broadcast(&mut self, value: IpAddr) -> Result<()> {
354 unsafe {
355 let mut req = self.request();
356 ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_broadaddr, OVERWRITE_SIZE);
357 if let Err(err) = siocsifbrdaddr(self.ctl.as_raw_fd(), &req) {
358 return Err(std::io::Error::from(err).into());
359 }
360 Ok(())
361 }
362 }
363
364 fn netmask(&self) -> Result<IpAddr> {
365 unsafe {
366 let mut req = self.request();
367 if let Err(err) = siocgifnetmask(self.ctl.as_raw_fd(), &mut req) {
368 return Err(std::io::Error::from(err).into());
369 }
370 let sa = sockaddr_union::from(req.ifr_ifru.ifru_netmask);
371 Ok(std::net::SocketAddr::try_from(sa)?.ip())
372 }
373 }
374
375 fn set_netmask(&mut self, value: IpAddr) -> Result<()> {
376 unsafe {
377 let mut req = self.request();
378 ipaddr_to_sockaddr(value, 0, &mut req.ifr_ifru.ifru_netmask, OVERWRITE_SIZE);
379 if let Err(err) = siocsifnetmask(self.ctl.as_raw_fd(), &req) {
380 return Err(std::io::Error::from(err).into());
381 }
382 Ok(())
383 }
384 }
385
386 fn mtu(&self) -> Result<u16> {
387 unsafe {
388 let mut req = self.request();
389
390 if let Err(err) = siocgifmtu(self.ctl.as_raw_fd(), &mut req) {
391 return Err(std::io::Error::from(err).into());
392 }
393
394 req.ifr_ifru
395 .ifru_mtu
396 .try_into()
397 .map_err(|_| Error::TryFromIntError)
398 }
399 }
400
401 fn set_mtu(&mut self, value: u16) -> Result<()> {
402 unsafe {
403 let mut req = self.request();
404 req.ifr_ifru.ifru_mtu = value as i32;
405
406 if let Err(err) = siocsifmtu(self.ctl.as_raw_fd(), &req) {
407 return Err(std::io::Error::from(err).into());
408 }
409 self.tun.set_mtu(value);
410 Ok(())
411 }
412 }
413
414 fn packet_information(&self) -> bool {
415 self.tun.packet_information()
416 }
417}
418
419impl AsRawFd for Device {
420 fn as_raw_fd(&self) -> RawFd {
421 self.tun.as_raw_fd()
422 }
423}
424
425impl IntoRawFd for Device {
426 fn into_raw_fd(self) -> RawFd {
427 self.tun.into_raw_fd()
428 }
429}
430
431impl From<Layer> for c_short {
432 fn from(layer: Layer) -> Self {
433 match layer {
434 Layer::L2 => IFF_TAP as c_short,
435 Layer::L3 => IFF_TUN as c_short,
436 }
437 }
438}