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