From eebd8e431a06cd2a17ae04908f63dcd5620f7e0a Mon Sep 17 00:00:00 2001 From: Ruben De Smet Date: Fri, 4 Oct 2019 11:10:20 +0200 Subject: [PATCH] Add ethernet feature-gate as default. Disable ethernet-related features and framing based on a feature gate. Add a no-ethernet option to Travis. notes: - allow(unused) is added when not using ethernet feature - Don't run pretty-print doctest, ethernet is optional. Closes: #308 Approved by: whitequark --- .travis.yml | 25 ++++++++++++++----------- Cargo.toml | 2 ++ src/iface/mod.rs | 6 ++++++ src/lib.rs | 4 ++-- src/parsers.rs | 9 +++++++-- src/phy/mod.rs | 1 + src/wire/icmpv6.rs | 8 +++++++- src/wire/mod.rs | 14 ++++++++------ src/wire/pretty_print.rs | 2 +- 9 files changed, 48 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0878088..2632ee3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,32 +12,35 @@ matrix: env: FEATURES='default' MODE='test' ### Test select feature permutations, chosen to be as orthogonal as possible - rust: nightly - env: FEATURES='std phy-raw_socket proto-ipv6 socket-udp' MODE='test' + env: FEATURES='std ethernet phy-raw_socket proto-ipv6 socket-udp' MODE='test' - rust: nightly - env: FEATURES='std phy-tap_interface proto-ipv6 socket-udp' MODE='test' + env: FEATURES='std ethernet phy-tap_interface proto-ipv6 socket-udp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv4 proto-igmp socket-raw' MODE='test' + env: FEATURES='std ethernet proto-ipv4 proto-igmp socket-raw' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv4 socket-udp socket-tcp' MODE='test' + env: FEATURES='std ethernet proto-ipv4 socket-udp socket-tcp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv4 proto-dhcpv4 socket-udp' MODE='test' + env: FEATURES='std ethernet proto-ipv4 proto-dhcpv4 socket-udp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv6 socket-udp' MODE='test' + env: FEATURES='std ethernet proto-ipv6 socket-udp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv6 socket-tcp' MODE='test' + env: FEATURES='std ethernet proto-ipv6 socket-tcp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv4 socket-icmp socket-tcp' MODE='test' + env: FEATURES='std ethernet proto-ipv4 socket-icmp socket-tcp' MODE='test' - rust: nightly - env: FEATURES='std proto-ipv6 socket-icmp socket-tcp' MODE='test' + env: FEATURES='std ethernet proto-ipv6 socket-icmp socket-tcp' MODE='test' ### Test select feature permutations, chosen to be as aggressive as possible - rust: nightly - env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std' + env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp std' + MODE='test' + - rust: nightly + env: FEATURES='ethernet proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc' MODE='test' - rust: nightly env: FEATURES='proto-ipv4 proto-ipv6 socket-raw socket-udp socket-tcp socket-icmp alloc' MODE='test' - rust: nightly - env: FEATURES='proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp' + env: FEATURES='ethernet proto-ipv4 proto-ipv6 proto-igmp proto-dhcpv4 socket-raw socket-udp socket-tcp socket-icmp' MODE='build' - rust: nightly env: MODE='fuzz run' ARGS='packet_parser -- -max_len=1536 -max_total_time=30' diff --git a/Cargo.toml b/Cargo.toml index 1ae094d..7ffc18a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ url = "1.0" std = ["managed/std"] alloc = ["managed/alloc"] verbose = [] +ethernet = [] "phy-raw_socket" = ["std", "libc"] "phy-tap_interface" = ["std", "libc"] "proto-ipv4" = [] @@ -43,6 +44,7 @@ verbose = [] "socket-icmp" = [] default = [ "std", "log", # needed for `cargo test --no-default-features --features default` :/ + "ethernet", "phy-raw_socket", "phy-tap_interface", "proto-ipv4", "proto-igmp", "proto-ipv6", "socket-raw", "socket-icmp", "socket-udp", "socket-tcp" diff --git a/src/iface/mod.rs b/src/iface/mod.rs index 09ece82..d38593f 100644 --- a/src/iface/mod.rs +++ b/src/iface/mod.rs @@ -4,13 +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")] mod neighbor; mod route; +#[cfg(feature = "ethernet")] mod ethernet; +#[cfg(feature = "ethernet")] pub use self::neighbor::Neighbor as Neighbor; +#[cfg(feature = "ethernet")] pub(crate) use self::neighbor::Answer as NeighborAnswer; +#[cfg(feature = "ethernet")] pub use self::neighbor::Cache as NeighborCache; pub use self::route::{Route, Routes}; +#[cfg(feature = "ethernet")] pub use self::ethernet::{Interface as EthernetInterface, InterfaceBuilder as EthernetInterfaceBuilder}; diff --git a/src/lib.rs b/src/lib.rs index 34c529c..9b6cea7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(feature = "alloc", feature(alloc))] #![no_std] #![deny(unsafe_code)] -#![cfg_attr(any(feature = "proto-ipv4", feature = "proto-ipv6"), deny(unused))] +#![cfg_attr(all(any(feature = "proto-ipv4", feature = "proto-ipv6"), feature = "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 @@ -91,7 +91,7 @@ compile_error!("at least one socket needs to be enabled"); */ // FIXME(dlrobertson): clippy fails with this lint #![cfg_attr(feature = "cargo-clippy", allow(if_same_then_else))] -#[cfg(feature = "proto-ipv6")] +#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] #[macro_use] extern crate bitflags; extern crate byteorder; diff --git a/src/parsers.rs b/src/parsers.rs index 9456d99..e645263 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -3,7 +3,9 @@ use core::str::FromStr; use core::result; -use wire::{EthernetAddress, IpAddress, IpCidr, IpEndpoint}; +#[cfg(feature = "ethernet")] +use wire::EthernetAddress; +use wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] use wire::{Ipv4Address, Ipv4Cidr}; #[cfg(feature = "proto-ipv6")] @@ -116,6 +118,7 @@ impl<'a> Parser<'a> { } } + #[cfg(feature = "ethernet")] fn accept_mac_joined_with(&mut self, separator: u8) -> Result { let mut octets = [0u8; 6]; for n in 0..6 { @@ -127,6 +130,7 @@ impl<'a> Parser<'a> { Ok(EthernetAddress(octets)) } + #[cfg(feature = "ethernet")] fn accept_mac(&mut self) -> Result { if let Some(mac) = self.try(|p| p.accept_mac_joined_with(b'-')) { return Ok(mac) @@ -344,6 +348,7 @@ impl<'a> Parser<'a> { } } +#[cfg(feature = "ethernet")] impl FromStr for EthernetAddress { type Err = (); @@ -462,7 +467,7 @@ mod test { } #[test] - #[cfg(feature = "proto-ipv4")] + #[cfg(all(feature = "proto-ipv4", feature = "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 ccc3d18..b458543 100644 --- a/src/phy/mod.rs +++ b/src/phy/mod.rs @@ -115,6 +115,7 @@ pub use self::raw_socket::RawSocket; #[cfg(all(feature = "phy-tap_interface", target_os = "linux"))] pub use self::tap_interface::TapInterface; +#[cfg(feature = "ethernet")] /// A tracer device for Ethernet frames. pub type EthernetTracer = Tracer>; diff --git a/src/wire/icmpv6.rs b/src/wire/icmpv6.rs index 212da96..fd18063 100644 --- a/src/wire/icmpv6.rs +++ b/src/wire/icmpv6.rs @@ -5,7 +5,9 @@ use {Error, Result}; use phy::ChecksumCapabilities; use super::ip::checksum; use super::{IpAddress, IpProtocol, Ipv6Packet, Ipv6Repr}; -use super::{MldRepr, NdiscRepr}; +use super::MldRepr; +#[cfg(feature = "ethernet")] +use super::NdiscRepr; enum_with_unknown! { /// Internet protocol control message type. @@ -537,6 +539,7 @@ pub enum Repr<'a> { seq_no: u16, data: &'a [u8] }, + #[cfg(feature = "ethernet")] Ndisc(NdiscRepr<'a>), Mld(MldRepr<'a>), #[doc(hidden)] @@ -619,6 +622,7 @@ impl<'a> Repr<'a> { data: packet.payload() }) }, + #[cfg(feature = "ethernet")] (msg_type, 0) if msg_type.is_ndisc() => { NdiscRepr::parse(packet).map(|repr| Repr::Ndisc(repr)) }, @@ -640,6 +644,7 @@ impl<'a> Repr<'a> { &Repr::EchoReply { data, .. } => { field::ECHO_SEQNO.end + data.len() }, + #[cfg(feature = "ethernet")] &Repr::Ndisc(ndisc) => { ndisc.buffer_len() }, @@ -711,6 +716,7 @@ impl<'a> Repr<'a> { packet.payload_mut()[..data_len].copy_from_slice(&data[..data_len]) }, + #[cfg(feature = "ethernet")] &Repr::Ndisc(ndisc) => { ndisc.emit(packet) }, diff --git a/src/wire/mod.rs b/src/wire/mod.rs index 20fb9ce..8641f14 100644 --- a/src/wire/mod.rs +++ b/src/wire/mod.rs @@ -77,8 +77,9 @@ mod field { pub mod pretty_print; +#[cfg(feature = "ethernet")] mod ethernet; -#[cfg(feature = "proto-ipv4")] +#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))] mod arp; pub(crate) mod ip; #[cfg(feature = "proto-ipv4")] @@ -101,9 +102,9 @@ mod icmpv6; mod icmp; #[cfg(feature = "proto-igmp")] mod igmp; -#[cfg(feature = "proto-ipv6")] +#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] mod ndisc; -#[cfg(feature = "proto-ipv6")] +#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] mod ndiscoption; #[cfg(feature = "proto-ipv6")] mod mld; @@ -114,12 +115,13 @@ pub(crate) mod dhcpv4; pub use self::pretty_print::PrettyPrinter; +#[cfg(feature = "ethernet")] pub use self::ethernet::{EtherType as EthernetProtocol, Address as EthernetAddress, Frame as EthernetFrame, Repr as EthernetRepr}; -#[cfg(feature = "proto-ipv4")] +#[cfg(all(feature = "proto-ipv4", feature = "ethernet"))] pub use self::arp::{Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, @@ -190,12 +192,12 @@ pub use self::icmpv6::{Message as Icmpv6Message, pub use self::icmp::Repr as IcmpRepr; -#[cfg(feature = "proto-ipv6")] +#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] pub use self::ndisc::{Repr as NdiscRepr, RouterFlags as NdiscRouterFlags, NeighborFlags as NdiscNeighborFlags}; -#[cfg(feature = "proto-ipv6")] +#[cfg(all(feature = "proto-ipv6", feature = "ethernet"))] pub use self::ndiscoption::{NdiscOption, Repr as NdiscOptionRepr, Type as NdiscOptionType, diff --git a/src/wire/pretty_print.rs b/src/wire/pretty_print.rs index 94bf7c6..c60c1ff 100644 --- a/src/wire/pretty_print.rs +++ b/src/wire/pretty_print.rs @@ -7,7 +7,7 @@ easily human readable packet listings. A packet can be formatted using the `PrettyPrinter` wrapper: -```rust +```rust,ignore use smoltcp::wire::*; let buffer = vec![ // Ethernet II