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 14 pub mod sys; 15 use std::fmt; 16 use std::fmt::Display; 17 use std::io::Read; 18 use std::io::Write; 19 use std::net; 20 use std::num::ParseIntError; 21 use std::os::raw::*; 22 use std::str::FromStr; 23 24 use base::AsRawDescriptor; 25 use base::Error as SysError; 26 use base::RawDescriptor; 27 use remain::sorted; 28 use serde::Deserialize; 29 use serde::Deserializer; 30 use serde::Serialize; 31 use serde::Serializer; 32 pub use sys::TapT; 33 use thiserror::Error as ThisError; 34 35 #[cfg(feature = "slirp")] 36 pub mod slirp; 37 #[cfg(all(feature = "slirp", windows))] 38 pub use slirp::Slirp; 39 40 #[sorted] 41 #[derive(ThisError, Debug)] 42 pub 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 63 pub type Result<T> = std::result::Result<T, Error>; 64 65 impl Error { sys_error(&self) -> SysError66 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)] 81 pub 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)] 92 pub struct MacAddress { 93 addr: [u8; 6], 94 } 95 96 impl MacAddress { octets(&self) -> [u8; 6]97 pub fn octets(&self) -> [u8; 6] { 98 self.addr 99 } 100 } 101 102 impl FromStr for MacAddress { 103 type Err = MacAddressError; 104 from_str(s: &str) -> std::result::Result<Self, Self::Err>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 121 impl Display for MacAddress { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result122 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 131 impl<'de> Deserialize<'de> for MacAddress { deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> where D: Deserializer<'de>,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 141 impl Serialize for MacAddress { serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> where S: Serializer,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 150 pub 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 new_with_name(name: &[u8], vnet_hdr: bool, multi_vq: bool) -> Result<Self>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. new(vnet_hdr: bool, multi_vq: bool) -> Result<Self>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. into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Self>>166 fn into_mq_taps(self, vq_pairs: u16) -> Result<Vec<Self>>; 167 168 /// Get the host-side IP address for the tap interface. ip_addr(&self) -> Result<net::Ipv4Addr>169 fn ip_addr(&self) -> Result<net::Ipv4Addr>; 170 171 /// Set the host-side IP address for the tap interface. set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>172 fn set_ip_addr(&self, ip_addr: net::Ipv4Addr) -> Result<()>; 173 174 /// Get the netmask for the tap interface's subnet. netmask(&self) -> Result<net::Ipv4Addr>175 fn netmask(&self) -> Result<net::Ipv4Addr>; 176 177 /// Set the netmask for the subnet that the tap interface will exist on. set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>178 fn set_netmask(&self, netmask: net::Ipv4Addr) -> Result<()>; 179 180 /// Get the MTU for the tap interface. mtu(&self) -> Result<u16>181 fn mtu(&self) -> Result<u16>; 182 183 /// Set the MTU for the tap interface. set_mtu(&self, mtu: u16) -> Result<()>184 fn set_mtu(&self, mtu: u16) -> Result<()>; 185 186 /// Get the mac address for the tap interface. mac_address(&self) -> Result<MacAddress>187 fn mac_address(&self) -> Result<MacAddress>; 188 189 /// Set the mac address for the tap interface. set_mac_address(&self, mac_addr: MacAddress) -> Result<()>190 fn set_mac_address(&self, mac_addr: MacAddress) -> Result<()>; 191 192 /// Set the offload flags for the tap interface. set_offload(&self, flags: c_uint) -> Result<()>193 fn set_offload(&self, flags: c_uint) -> Result<()>; 194 195 /// Enable the tap interface. enable(&self) -> Result<()>196 fn enable(&self) -> Result<()>; 197 198 /// Try to clone try_clone(&self) -> Result<Self>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. from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self>207 unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Result<Self>; 208 } 209 210 #[cfg(test)] 211 mod tests { 212 use serde_json::*; 213 214 use super::*; 215 216 #[test] json_serialize_deserialize()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 } 229