net_util/
lib.rs

1// Copyright 2017 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Network API wrappers for TAP interfaces.
6//! # Slirp specific crate features
7//! * **guest-to-host-net-loopback** - Enables the guest to reach the host at a well known IP
8//!   address on the virtual network.
9//! * **slirp** - Enables the libslirp backend for virtio-net.
10//! * **slirp-debug** - Enables capture of all packets sent through libslirp in a pcap file.
11//! * **slirp-ring-capture** - Captures packets in a ring buffer and dumps them to a pcap file on
12//!   exit.
13
14pub mod sys;
15use std::fmt;
16use std::fmt::Display;
17use std::io::Read;
18use std::io::Write;
19use std::net;
20use std::num::ParseIntError;
21use std::os::raw::*;
22use std::str::FromStr;
23
24use base::AsRawDescriptor;
25use base::Error as SysError;
26use base::RawDescriptor;
27use remain::sorted;
28use serde::Deserialize;
29use serde::Deserializer;
30use serde::Serialize;
31use serde::Serializer;
32pub use sys::TapT;
33use thiserror::Error as ThisError;
34
35#[cfg(feature = "slirp")]
36pub mod slirp;
37#[cfg(all(feature = "slirp", windows))]
38pub use slirp::Slirp;
39
40#[sorted]
41#[derive(ThisError, Debug)]
42pub enum Error {
43    /// Unable to clone tap interface.
44    #[error("failed to clone tap interface: {0}")]
45    CloneTap(SysError),
46    /// Failed to create a socket.
47    #[error("failed to create a socket: {0}")]
48    CreateSocket(SysError),
49    /// Unable to create tap interface.
50    #[error("failed to create tap interface: {0}")]
51    CreateTap(SysError),
52    /// ioctl failed.
53    #[error("ioctl failed: {0}")]
54    IoctlError(SysError),
55    /// Couldn't open /dev/net/tun.
56    #[error("failed to open /dev/net/tun: {0}")]
57    OpenTun(SysError),
58    #[cfg(all(feature = "slirp", windows))]
59    #[error("slirp related error")]
60    Slirp(slirp::SlirpError),
61}
62
63pub type Result<T> = std::result::Result<T, Error>;
64
65impl Error {
66    pub fn sys_error(&self) -> SysError {
67        match self {
68            Error::CreateSocket(e) => *e,
69            Error::OpenTun(e) => *e,
70            Error::CreateTap(e) => *e,
71            Error::CloneTap(e) => *e,
72            Error::IoctlError(e) => *e,
73            #[cfg(all(feature = "slirp", windows))]
74            Error::Slirp(e) => e.sys_error(),
75        }
76    }
77}
78
79#[sorted]
80#[derive(ThisError, Debug, PartialEq, Eq)]
81pub enum MacAddressError {
82    /// Invalid number of octets.
83    #[error("invalid number of octets: {0}")]
84    InvalidNumOctets(usize),
85    /// Failed to parse octet.
86    #[error("failed to parse octet: {0}")]
87    ParseOctet(ParseIntError),
88}
89
90/// An Ethernet MAC address.
91#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
92pub struct MacAddress {
93    addr: [u8; 6],
94}
95
96impl MacAddress {
97    pub fn octets(&self) -> [u8; 6] {
98        self.addr
99    }
100}
101
102impl FromStr for MacAddress {
103    type Err = MacAddressError;
104
105    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
106        let octets: Vec<&str> = s.split(':').collect();
107        if octets.len() != 6usize {
108            return Err(MacAddressError::InvalidNumOctets(octets.len()));
109        }
110
111        let mut result = MacAddress::default();
112
113        for (i, octet) in octets.iter().enumerate() {
114            result.addr[i] = u8::from_str_radix(octet, 16).map_err(MacAddressError::ParseOctet)?;
115        }
116
117        Ok(result)
118    }
119}
120
121impl Display for MacAddress {
122    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
123        write!(
124            f,
125            "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
126            self.addr[0], self.addr[1], self.addr[2], self.addr[3], self.addr[4], self.addr[5]
127        )
128    }
129}
130
131impl<'de> Deserialize<'de> for MacAddress {
132    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
133    where
134        D: Deserializer<'de>,
135    {
136        let s = String::deserialize(deserializer)?;
137        FromStr::from_str(&s).map_err(serde::de::Error::custom)
138    }
139}
140
141impl Serialize for MacAddress {
142    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
143    where
144        S: Serializer,
145    {
146        serializer.collect_str(&self)
147    }
148}
149
150pub trait TapTCommon: Read + Write + AsRawDescriptor + Send + Sized {
151    /// Create a new tap interface named `name`, or open it if it already exists with the same
152    /// parameters.
153    ///
154    /// Set the `vnet_hdr` flag to true to allow offloading on this tap, which will add an extra 12
155    /// byte virtio net header to incoming frames. Offloading cannot be used if `vnet_hdr` is false.
156    /// Set 'multi_vq' to true, if tap have multi virt queue pairs
157    fn new_with_name(name: &[u8], vnet_hdr: bool, multi_vq: bool) -> Result<Self>;
158
159    /// Create a new tap interface. Set the `vnet_hdr` flag to true to allow offloading on this tap,
160    /// which will add an extra 12 byte virtio net header to incoming frames. Offloading cannot
161    /// be used if `vnet_hdr` is false. Set 'multi_vq' to true if tap has multi virt queue pairs.
162    fn new(vnet_hdr: bool, multi_vq: bool) -> Result<Self>;
163
164    /// Change the origin tap into multiqueue taps, this means create other taps based on the
165    /// origin tap.
166    fn into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Self>>;
167
168    /// Get the host-side IP address for the tap interface.
169    fn ip_addr(&self) -> Result<net::Ipv4Addr>;
170
171    /// Set the host-side IP address for the tap interface.
172    fn set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>;
173
174    /// Get the netmask for the tap interface's subnet.
175    fn netmask(&self) -> Result<net::Ipv4Addr>;
176
177    /// Set the netmask for the subnet that the tap interface will exist on.
178    fn set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>;
179
180    /// Get the MTU for the tap interface.
181    fn mtu(&self) -> Result<u16>;
182
183    /// Set the MTU for the tap interface.
184    fn set_mtu(&self, mtu: u16) -> Result<()>;
185
186    /// Get the mac address for the tap interface.
187    fn mac_address(&self) -> Result<MacAddress>;
188
189    /// Set the mac address for the tap interface.
190    fn set_mac_address(&self, mac_addr: MacAddress) -> Result<()>;
191
192    /// Set the offload flags for the tap interface.
193    fn set_offload(&self, flags: c_uint) -> Result<()>;
194
195    /// Enable the tap interface.
196    fn enable(&self) -> Result<()>;
197
198    /// Try to clone
199    fn try_clone(&self) -> Result<Self>;
200
201    /// Convert raw descriptor to
202    ///
203    /// # Safety
204    ///
205    /// Caller must ensure that RawDescriptor stays valid as long as the lifetime
206    /// of Self.
207    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self>;
208}
209
210#[cfg(test)]
211mod tests {
212    use serde_json::*;
213
214    use super::*;
215
216    #[test]
217    fn json_serialize_deserialize() {
218        let mac_address = MacAddress {
219            addr: [0x3d, 0x70, 0xeb, 0x61, 0x1a, 0x91],
220        };
221        const SERIALIZED_ADDRESS: &str = "\"3D:70:EB:61:1A:91\"";
222        assert_eq!(to_string(&mac_address).unwrap(), SERIALIZED_ADDRESS);
223        assert_eq!(
224            from_str::<MacAddress>(SERIALIZED_ADDRESS).unwrap(),
225            mac_address
226        );
227    }
228}