diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80b7550..adf2bd1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,23 +26,23 @@ jobs: - std proto-ipv4 # Test features chosen to be as orthogonal as possible. - - std ethernet phy-raw_socket proto-ipv6 socket-udp - - std ethernet phy-tap_interface proto-ipv6 socket-udp - - std ethernet proto-ipv4 proto-igmp socket-raw - - std ethernet proto-ipv4 socket-udp socket-tcp - - std ethernet proto-ipv4 proto-dhcpv4 socket-udp - - std ethernet proto-ipv6 socket-udp - - std ethernet proto-ipv6 socket-tcp - - std ethernet proto-ipv4 socket-icmp socket-tcp - - std ethernet proto-ipv6 socket-icmp socket-tcp + - std medium-ethernet phy-raw_socket proto-ipv6 socket-udp + - std medium-ethernet phy-tap_interface proto-ipv6 socket-udp + - std medium-ethernet proto-ipv4 proto-igmp socket-raw + - std medium-ethernet proto-ipv4 socket-udp socket-tcp + - std medium-ethernet proto-ipv4 proto-dhcpv4 socket-udp + - std medium-ethernet proto-ipv6 socket-udp + - std medium-ethernet proto-ipv6 socket-tcp + - std medium-ethernet proto-ipv4 socket-icmp socket-tcp + - std medium-ethernet proto-ipv6 socket-icmp socket-tcp # Test features chosen to be as aggressive as possible. - - std ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async + - std medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp async include: # Test alloc feature which requires nightly. - rust: nightly - features: alloc ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp + features: alloc medium-ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp - rust: nightly features: alloc proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp steps: @@ -69,7 +69,7 @@ jobs: features: # These feature sets cannot run tests, so we only check they build. - - ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async + - medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp async steps: - uses: actions/checkout@v2 diff --git a/Cargo.toml b/Cargo.toml index 125c4ad..a5b9833 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,8 @@ url = "1.0" std = ["managed/std"] alloc = ["managed/alloc"] verbose = [] -ethernet = ["socket"] +"medium-ethernet" = ["socket"] +"medium-ip" = ["socket"] "phy-raw_socket" = ["std", "libc", "ethernet"] "phy-tap_interface" = ["std", "libc", "ethernet"] "proto-ipv4" = [] @@ -47,7 +48,7 @@ ethernet = ["socket"] "async" = [] default = [ "std", "log", # needed for `cargo test --no-default-features --features default` :/ - "ethernet", + "medium-ethernet", "medium-ip", "phy-raw_socket", "phy-tap_interface", "proto-ipv4", "proto-igmp", "proto-dhcpv4", "proto-ipv6", "socket-raw", "socket-icmp", "socket-udp", "socket-tcp", diff --git a/src/iface/interface.rs b/src/iface/interface.rs index 5fd518f..2f43c1e 100644 --- a/src/iface/interface.rs +++ b/src/iface/interface.rs @@ -10,7 +10,7 @@ use crate::phy::{Device, DeviceCapabilities, RxToken, TxToken, Medium}; use crate::time::{Duration, Instant}; use crate::wire::*; use crate::socket::*; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] use crate::iface::{NeighborCache, NeighborAnswer}; use crate::iface::Routes; @@ -32,9 +32,9 @@ pub struct Interface<'a, DeviceT: for<'d> Device<'d>> { /// methods on the `Interface` in this time (since its `device` field is borrowed /// exclusively). However, it is still possible to call methods on its `inner` field. struct InterfaceInner<'a> { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] neighbor_cache: Option>, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] ethernet_addr: Option, ip_addrs: ManagedSlice<'a, IpCidr>, #[cfg(feature = "proto-ipv4")] @@ -51,9 +51,9 @@ struct InterfaceInner<'a> { /// A builder structure used for creating a network interface. pub struct InterfaceBuilder <'a, DeviceT: for<'d> Device<'d>> { device: DeviceT, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] ethernet_addr: Option, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] neighbor_cache: Option>, ip_addrs: ManagedSlice<'a, IpCidr>, #[cfg(feature = "proto-ipv4")] @@ -68,7 +68,7 @@ impl<'a, DeviceT> InterfaceBuilder<'a, DeviceT> where DeviceT: for<'d> Device<'d> { /// Create a builder used for creating a network interface using the /// given device and address. - #[cfg_attr(feature = "ethernet", doc = r##" + #[cfg_attr(feature = "medium-ethernet", doc = r##" # Examples ``` @@ -95,9 +95,9 @@ let iface = InterfaceBuilder::new(device) pub fn new(device: DeviceT) -> Self { InterfaceBuilder { device: device, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] ethernet_addr: None, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] neighbor_cache: None, ip_addrs: ManagedSlice::Borrowed(&mut []), #[cfg(feature = "proto-ipv4")] @@ -115,7 +115,7 @@ let iface = InterfaceBuilder::new(device) /// This function panics if the address is not unicast. /// /// [ethernet_addr]: struct.Interface.html#method.ethernet_addr - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] pub fn ethernet_addr(mut self, addr: EthernetAddress) -> Self { InterfaceInner::check_ethernet_addr(&addr); self.ethernet_addr = Some(addr); @@ -187,7 +187,7 @@ let iface = InterfaceBuilder::new(device) } /// Set the Neighbor Cache the interface will use. - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] pub fn neighbor_cache(mut self, neighbor_cache: NeighborCache<'a>) -> Self { self.neighbor_cache = Some(neighbor_cache); self @@ -207,35 +207,31 @@ let iface = InterfaceBuilder::new(device) pub fn finalize(self) -> Interface<'a, DeviceT> { let device_capabilities = self.device.capabilities(); - #[cfg(feature = "ethernet")] - let mut ethernet_addr = None; - #[cfg(feature = "ethernet")] - let mut neighbor_cache = None; - match device_capabilities.medium { - #[cfg(feature = "ethernet")] - Medium::Ethernet => { - ethernet_addr = Some(self.ethernet_addr.expect("ethernet_addr required option was not set")); - neighbor_cache = Some(self.neighbor_cache.expect("neighbor_cache required option was not set")); - } + #[cfg(feature = "medium-ethernet")] + let (ethernet_addr, neighbor_cache) = match device_capabilities.medium { + Medium::Ethernet => ( + Some(self.ethernet_addr.expect("ethernet_addr required option was not set")), + Some(self.neighbor_cache.expect("neighbor_cache required option was not set")) + ), + #[cfg(feature = "medium-ip")] Medium::Ip => { - #[cfg(feature = "ethernet")] assert!(self.ethernet_addr.is_none(), "ethernet_addr is set, but device medium is IP"); - #[cfg(feature = "ethernet")] assert!(self.neighbor_cache.is_none(), "neighbor_cache is set, but device medium is IP"); + (None, None) } - } + }; Interface { device: self.device, inner: InterfaceInner { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] ethernet_addr, ip_addrs: self.ip_addrs, #[cfg(feature = "proto-ipv4")] any_ip: self.any_ip, routes: self.routes, device_capabilities, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] neighbor_cache, #[cfg(feature = "proto-igmp")] ipv4_multicast_groups: self.ipv4_multicast_groups, @@ -247,7 +243,7 @@ let iface = InterfaceBuilder::new(device) } #[derive(Debug, PartialEq)] -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] enum EthernetPacket<'a> { #[cfg(feature = "proto-ipv4")] Arp(ArpRepr), @@ -371,7 +367,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// # Panics /// This function panics if if the interface's medium is not Ethernet. - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] pub fn ethernet_addr(&self) -> EthernetAddress { self.inner.ethernet_addr.unwrap() } @@ -381,7 +377,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> /// # Panics /// This function panics if the address is not unicast, or if the /// interface's medium is not Ethernet. - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] pub fn set_ethernet_addr(&mut self, addr: EthernetAddress) { assert!(self.device.capabilities().medium == Medium::Ethernet); InterfaceInner::check_ethernet_addr(&addr); @@ -591,7 +587,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> }; rx_token.consume(timestamp, |frame| { match inner.device_capabilities.medium { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Medium::Ethernet => { inner.process_ethernet(sockets, timestamp, &frame).map_err(|err| { net_debug!("cannot process ingress packet: {}", err); @@ -611,6 +607,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> } }) } + #[cfg(feature = "medium-ip")] Medium::Ip => { inner.process_ip(sockets, timestamp, &frame).map_err(|err| { net_debug!("cannot process ingress packet: {}", err); @@ -638,12 +635,12 @@ impl<'a, DeviceT> Interface<'a, DeviceT> fn socket_egress(&mut self, sockets: &mut SocketSet, timestamp: Instant) -> Result { let mut caps = self.device.capabilities(); - match caps.medium { - #[cfg(feature = "ethernet")] - Medium::Ethernet => - caps.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len(), - _ => {} - } + caps.max_transmission_unit = match caps.medium { + #[cfg(feature = "medium-ethernet")] + Medium::Ethernet => caps.max_transmission_unit - EthernetFrame::<&[u8]>::header_len(), + #[cfg(feature = "medium-ip")] + Medium::Ip => caps.max_transmission_unit, + }; let mut emitted_any = false; for mut socket in sockets.iter_mut() { @@ -768,7 +765,7 @@ impl<'a, DeviceT> Interface<'a, DeviceT> } impl<'a> InterfaceInner<'a> { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn check_ethernet_addr(addr: &EthernetAddress) { if addr.is_multicast() { panic!("Ethernet address {} is not unicast", addr) @@ -836,7 +833,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn process_ethernet<'frame, T: AsRef<[u8]>> (&mut self, sockets: &mut SocketSet, timestamp: Instant, frame: &'frame T) -> Result>> @@ -887,6 +884,7 @@ impl<'a> InterfaceInner<'a> { } } + #[cfg(feature = "medium-ip")] fn process_ip<'frame, T: AsRef<[u8]>> (&mut self, sockets: &mut SocketSet, timestamp: Instant, ip_payload: &'frame T) -> Result>> @@ -907,7 +905,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(all(feature = "ethernet", feature = "proto-ipv4"))] + #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))] fn process_arp<'frame, T: AsRef<[u8]>> (&mut self, timestamp: Instant, eth_frame: &EthernetFrame<&'frame T>) -> Result>> @@ -1215,7 +1213,7 @@ impl<'a> InterfaceInner<'a> { Icmpv6Repr::EchoReply { .. } => Ok(None), // Forward any NDISC packets to the ndisc packet handler - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Icmpv6Repr::Ndisc(repr) if ip_repr.hop_limit() == 0xff => match ip_repr { IpRepr::Ipv6(ipv6_repr) => self.process_ndisc(_timestamp, ipv6_repr, repr), _ => Ok(None) @@ -1231,7 +1229,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(all(feature = "ethernet", feature = "proto-ipv6"))] + #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))] fn process_ndisc<'frame>(&mut self, timestamp: Instant, ip_repr: Ipv6Repr, repr: NdiscRepr<'frame>) -> Result>> { match repr { @@ -1503,7 +1501,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn dispatch(&mut self, tx_token: Tx, timestamp: Instant, packet: EthernetPacket) -> Result<()> where Tx: TxToken @@ -1530,7 +1528,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn dispatch_ethernet(&mut self, tx_token: Tx, timestamp: Instant, buffer_len: usize, f: F) -> Result<()> where Tx: TxToken, F: FnOnce(EthernetFrame<&mut [u8]>) @@ -1570,10 +1568,11 @@ impl<'a> InterfaceInner<'a> { match self.route(addr, timestamp) { Ok(_routed_addr) => { match self.device_capabilities.medium { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Medium::Ethernet => self.neighbor_cache.as_ref().unwrap() .lookup(&_routed_addr, timestamp) .found(), + #[cfg(feature = "medium-ip")] Medium::Ip => true, } } @@ -1581,7 +1580,7 @@ impl<'a> InterfaceInner<'a> { } } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn lookup_hardware_addr(&mut self, tx_token: Tx, timestamp: Instant, src_addr: &IpAddress, dst_addr: &IpAddress) -> Result<(EthernetAddress, Tx)> @@ -1682,7 +1681,7 @@ impl<'a> InterfaceInner<'a> { let caps = self.device_capabilities.clone(); match self.device_capabilities.medium { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Medium::Ethernet => { let (dst_hardware_addr, tx_token) = self.lookup_hardware_addr(tx_token, timestamp, @@ -1704,6 +1703,7 @@ impl<'a> InterfaceInner<'a> { packet.emit_payload(ip_repr, payload, &caps); }) } + #[cfg(feature = "medium-ip")] Medium::Ip => { let tx_len = ip_repr.total_len(); tx_token.consume(timestamp, tx_len, |mut tx_buffer| { @@ -1773,6 +1773,15 @@ mod test { use crate::phy::{Loopback, ChecksumCapabilities}; fn create_loopback<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) { + #[cfg(feature = "medium-ethernet")] + return create_loopback_ethernet(); + #[cfg(not(feature = "medium-ethernet"))] + return create_loopback_ip(); + } + + #[cfg(all(feature = "medium-ip"))] + #[allow(unused)] + fn create_loopback_ip<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) { // Create a basic device let device = Loopback::new(Medium::Ip); let ip_addrs = [ @@ -1795,7 +1804,7 @@ mod test { (iface, SocketSet::new(vec![])) } - #[cfg(all(feature = "ethernet"))] + #[cfg(all(feature = "medium-ethernet"))] fn create_loopback_ethernet<'a>() -> (Interface<'a, Loopback>, SocketSet<'a>) { // Create a basic device let device = Loopback::new(Medium::Ethernet); @@ -1845,7 +1854,7 @@ mod test { #[test] #[should_panic(expected = "ethernet_addr required option was not set")] - #[cfg(all(feature = "ethernet"))] + #[cfg(all(feature = "medium-ethernet"))] fn test_builder_initialization_panic() { InterfaceBuilder::new(Loopback::new(Medium::Ethernet)).finalize(); } @@ -2300,7 +2309,7 @@ mod test { } #[test] - #[cfg(all(feature = "ethernet", feature = "proto-ipv4"))] + #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))] fn test_handle_valid_arp_request() { let (mut iface, mut socket_set) = create_loopback_ethernet(); @@ -2345,7 +2354,7 @@ mod test { } #[test] - #[cfg(all(feature = "ethernet", feature = "proto-ipv6"))] + #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv6"))] fn test_handle_valid_ndisc_request() { let (mut iface, mut socket_set) = create_loopback_ethernet(); @@ -2405,7 +2414,7 @@ mod test { } #[test] - #[cfg(all(feature = "ethernet", feature = "proto-ipv4"))] + #[cfg(all(feature = "medium-ethernet", feature = "proto-ipv4"))] fn test_handle_other_arp_request() { let (mut iface, mut socket_set) = create_loopback_ethernet(); @@ -2589,11 +2598,21 @@ mod test { #[cfg(feature = "proto-igmp")] fn test_handle_igmp() { fn recv_igmp(mut iface: &mut Interface<'_, Loopback>, timestamp: Instant) -> Vec<(Ipv4Repr, IgmpRepr)> { - let checksum_caps = &iface.device.capabilities().checksum; + let caps = iface.device.capabilities(); + let checksum_caps = &caps.checksum; recv_all(&mut iface, timestamp) .iter() .filter_map(|frame| { - let ipv4_packet = Ipv4Packet::new_checked(frame).ok()?; + + let ipv4_packet = match caps.medium { + #[cfg(feature = "medium-ethernet")] + Medium::Ethernet => { + let eth_frame = EthernetFrame::new_checked(frame).ok()?; + Ipv4Packet::new_checked(eth_frame.payload()).ok()? + } + #[cfg(feature = "medium-ip")] + Medium::Ip => Ipv4Packet::new_checked(&frame[..]).ok()? + }; let ipv4_repr = Ipv4Repr::parse(&ipv4_packet, &checksum_caps).ok()?; let ip_payload = ipv4_packet.payload(); let igmp_packet = IgmpPacket::new_checked(ip_payload).ok()?; diff --git a/src/iface/mod.rs b/src/iface/mod.rs index a21bc25..1b4f32d 100644 --- a/src/iface/mod.rs +++ b/src/iface/mod.rs @@ -4,17 +4,19 @@ The `iface` module deals with the *network interfaces*. It filters incoming fram provides lookup and caching of hardware addresses, and handles management packets. */ -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] mod neighbor; mod route; +#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))] mod interface; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] pub use self::neighbor::Neighbor as Neighbor; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] pub(crate) use self::neighbor::Answer as NeighborAnswer; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] pub use self::neighbor::Cache as NeighborCache; pub use self::route::{Route, Routes}; +#[cfg(any(feature = "medium-ethernet", feature = "medium-ip"))] pub use self::interface::{Interface, InterfaceBuilder}; diff --git a/src/lib.rs b/src/lib.rs index 624b6b9..f143055 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr(not(any(test, feature = "std")), no_std)] #![deny(unsafe_code)] -#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "ethernet"), deny(unused))] +#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "medium-ethernet"), deny(unused))] //! The _smoltcp_ library is built in a layered structure, with the layers corresponding //! to the levels of API abstraction. Only the highest layers would be used by a typical diff --git a/src/parsers.rs b/src/parsers.rs index bf87cdc..136e58b 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -3,7 +3,7 @@ use core::str::FromStr; use core::result; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] use crate::wire::EthernetAddress; use crate::wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] @@ -118,7 +118,7 @@ impl<'a> Parser<'a> { } } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn accept_mac_joined_with(&mut self, separator: u8) -> Result { let mut octets = [0u8; 6]; for (n, octet) in octets.iter_mut().enumerate() { @@ -130,7 +130,7 @@ impl<'a> Parser<'a> { Ok(EthernetAddress(octets)) } - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] fn accept_mac(&mut self) -> Result { if let Some(mac) = self.try_do(|p| p.accept_mac_joined_with(b'-')) { return Ok(mac) @@ -352,7 +352,7 @@ impl<'a> Parser<'a> { } } -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] impl FromStr for EthernetAddress { type Err = (); @@ -473,7 +473,7 @@ mod test { } #[test] - #[cfg(all(feature = "proto-ipv4", feature = "ethernet"))] + #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] fn test_mac() { assert_eq!(EthernetAddress::from_str(""), Err(())); assert_eq!(EthernetAddress::from_str("02:00:00:00:00:00"), diff --git a/src/phy/mod.rs b/src/phy/mod.rs index 99947af..eadd0dc 100644 --- a/src/phy/mod.rs +++ b/src/phy/mod.rs @@ -11,7 +11,7 @@ and implementations of it: [TapInterface](struct.TapInterface.html), to transmit and receive frames on the host OS. */ -#![cfg_attr(feature = "ethernet", doc = r##" +#![cfg_attr(feature = "medium-ethernet", doc = r##" # Examples An implementation of the [Device](trait.Device.html) trait for a simple hardware @@ -117,7 +117,7 @@ pub use self::raw_socket::RawSocket; #[cfg(all(feature = "phy-tap_interface", any(target_os = "linux", target_os = "android")))] pub use self::tap_interface::TapInterface; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] /// A tracer device for Ethernet frames. pub type EthernetTracer = Tracer>; @@ -238,23 +238,26 @@ pub enum Medium { /// and interfaces using it must do neighbor discovery via ARP or NDISC. /// /// Examples of devices of this type are Ethernet, WiFi (802.11), Linux `tap`, and VPNs in tap (layer 2) mode. - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Ethernet, /// IP medium. Devices of this type send and receive IP frames, without an /// Ethernet header. MAC addresses are not used, and no neighbor discovery (ARP, NDISC) is done. /// /// Examples of devices of this type are the Linux `tun`, PPP interfaces, VPNs in tun (layer 3) mode. + #[cfg(feature = "medium-ip")] Ip, } impl Default for Medium { fn default() -> Medium { - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] return Medium::Ethernet; - #[cfg(not(feature = "ethernet"))] + #[cfg(all(feature = "medium-ip", not(feature = "medium-ethernet")))] return Medium::Ip; + #[cfg(all(not(feature = "medium-ip"), not(feature = "medium-ethernet")))] + panic!("No medium enabled"); } } diff --git a/src/wire/icmpv6.rs b/src/wire/icmpv6.rs index 597414a..a347a03 100644 --- a/src/wire/icmpv6.rs +++ b/src/wire/icmpv6.rs @@ -6,7 +6,7 @@ use crate::phy::ChecksumCapabilities; use crate::wire::ip::checksum; use crate::wire::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr}; use crate::wire::MldRepr; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] use crate::wire::NdiscRepr; enum_with_unknown! { @@ -536,7 +536,7 @@ pub enum Repr<'a> { seq_no: u16, data: &'a [u8] }, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Ndisc(NdiscRepr<'a>), Mld(MldRepr<'a>), } @@ -617,7 +617,7 @@ impl<'a> Repr<'a> { data: packet.payload() }) }, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] (msg_type, 0) if msg_type.is_ndisc() => { NdiscRepr::parse(packet).map(Repr::Ndisc) }, @@ -639,7 +639,7 @@ impl<'a> Repr<'a> { &Repr::EchoReply { data, .. } => { field::ECHO_SEQNO.end + data.len() }, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] &Repr::Ndisc(ndisc) => { ndisc.buffer_len() }, @@ -710,7 +710,7 @@ impl<'a> Repr<'a> { packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len]) }, - #[cfg(feature = "ethernet")] + #[cfg(feature = "medium-ethernet")] Repr::Ndisc(ndisc) => { ndisc.emit(packet) }, diff --git a/src/wire/mod.rs b/src/wire/mod.rs index c813c7b..4fee202 100644 --- a/src/wire/mod.rs +++ b/src/wire/mod.rs @@ -77,9 +77,9 @@ mod field { pub mod pretty_print; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] mod ethernet; -#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] mod arp; pub(crate) mod ip; #[cfg(feature = "proto-ipv4")] @@ -102,9 +102,9 @@ mod icmpv6; mod icmp; #[cfg(feature = "proto-igmp")] mod igmp; -#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] mod ndisc; -#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] mod ndiscoption; #[cfg(feature = "proto-ipv6")] mod mld; @@ -115,14 +115,14 @@ pub(crate) mod dhcpv4; pub use self::pretty_print::PrettyPrinter; -#[cfg(feature = "ethernet")] +#[cfg(feature = "medium-ethernet")] pub use self::ethernet::{EtherType as EthernetProtocol, Address as EthernetAddress, Frame as EthernetFrame, HEADER_LEN as ETHERNET_HEADER_LEN, Repr as EthernetRepr}; -#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))] pub use self::arp::{Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, @@ -193,12 +193,12 @@ pub use self::icmpv6::{Message as Icmpv6Message, pub use self::icmp::Repr as IcmpRepr; -#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] pub use self::ndisc::{Repr as NdiscRepr, RouterFlags as NdiscRouterFlags, NeighborFlags as NdiscNeighborFlags}; -#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] +#[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))] pub use self::ndiscoption::{NdiscOption, Repr as NdiscOptionRepr, Type as NdiscOptionType,