ethernet.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. use byteorder::{ByteOrder, NetworkEndian};
  2. use core::fmt;
  3. use super::{Error, Result};
  4. enum_with_unknown! {
  5. /// Ethernet protocol type.
  6. pub enum EtherType(u16) {
  7. Ipv4 = 0x0800,
  8. Arp = 0x0806,
  9. Ipv6 = 0x86DD
  10. }
  11. }
  12. impl fmt::Display for EtherType {
  13. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  14. match *self {
  15. EtherType::Ipv4 => write!(f, "IPv4"),
  16. EtherType::Ipv6 => write!(f, "IPv6"),
  17. EtherType::Arp => write!(f, "ARP"),
  18. EtherType::Unknown(id) => write!(f, "0x{:04x}", id),
  19. }
  20. }
  21. }
  22. /// A six-octet Ethernet II address.
  23. #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
  24. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  25. pub struct Address(pub [u8; 6]);
  26. impl Address {
  27. /// The broadcast address.
  28. pub const BROADCAST: Address = Address([0xff; 6]);
  29. /// Construct an Ethernet address from a sequence of octets, in big-endian.
  30. ///
  31. /// # Panics
  32. /// The function panics if `data` is not six octets long.
  33. pub fn from_bytes(data: &[u8]) -> Address {
  34. let mut bytes = [0; 6];
  35. bytes.copy_from_slice(data);
  36. Address(bytes)
  37. }
  38. /// Return an Ethernet address as a sequence of octets, in big-endian.
  39. pub const fn as_bytes(&self) -> &[u8] {
  40. &self.0
  41. }
  42. /// Query whether the address is an unicast address.
  43. pub fn is_unicast(&self) -> bool {
  44. !(self.is_broadcast() || self.is_multicast())
  45. }
  46. /// Query whether this address is the broadcast address.
  47. pub fn is_broadcast(&self) -> bool {
  48. *self == Self::BROADCAST
  49. }
  50. /// Query whether the "multicast" bit in the OUI is set.
  51. pub const fn is_multicast(&self) -> bool {
  52. self.0[0] & 0x01 != 0
  53. }
  54. /// Query whether the "locally administered" bit in the OUI is set.
  55. pub const fn is_local(&self) -> bool {
  56. self.0[0] & 0x02 != 0
  57. }
  58. }
  59. impl fmt::Display for Address {
  60. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  61. let bytes = self.0;
  62. write!(
  63. f,
  64. "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
  65. bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]
  66. )
  67. }
  68. }
  69. /// A read/write wrapper around an Ethernet II frame buffer.
  70. #[derive(Debug, Clone)]
  71. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  72. pub struct Frame<T: AsRef<[u8]>> {
  73. buffer: T,
  74. }
  75. mod field {
  76. use crate::wire::field::*;
  77. pub const DESTINATION: Field = 0..6;
  78. pub const SOURCE: Field = 6..12;
  79. pub const ETHERTYPE: Field = 12..14;
  80. pub const PAYLOAD: Rest = 14..;
  81. }
  82. /// The Ethernet header length
  83. pub const HEADER_LEN: usize = field::PAYLOAD.start;
  84. impl<T: AsRef<[u8]>> Frame<T> {
  85. /// Imbue a raw octet buffer with Ethernet frame structure.
  86. pub const fn new_unchecked(buffer: T) -> Frame<T> {
  87. Frame { buffer }
  88. }
  89. /// Shorthand for a combination of [new_unchecked] and [check_len].
  90. ///
  91. /// [new_unchecked]: #method.new_unchecked
  92. /// [check_len]: #method.check_len
  93. pub fn new_checked(buffer: T) -> Result<Frame<T>> {
  94. let packet = Self::new_unchecked(buffer);
  95. packet.check_len()?;
  96. Ok(packet)
  97. }
  98. /// Ensure that no accessor method will panic if called.
  99. /// Returns `Err(Error)` if the buffer is too short.
  100. pub fn check_len(&self) -> Result<()> {
  101. let len = self.buffer.as_ref().len();
  102. if len < HEADER_LEN {
  103. Err(Error)
  104. } else {
  105. Ok(())
  106. }
  107. }
  108. /// Consumes the frame, returning the underlying buffer.
  109. pub fn into_inner(self) -> T {
  110. self.buffer
  111. }
  112. /// Return the length of a frame header.
  113. pub const fn header_len() -> usize {
  114. HEADER_LEN
  115. }
  116. /// Return the length of a buffer required to hold a packet with the payload
  117. /// of a given length.
  118. pub const fn buffer_len(payload_len: usize) -> usize {
  119. HEADER_LEN + payload_len
  120. }
  121. /// Return the destination address field.
  122. #[inline]
  123. pub fn dst_addr(&self) -> Address {
  124. let data = self.buffer.as_ref();
  125. Address::from_bytes(&data[field::DESTINATION])
  126. }
  127. /// Return the source address field.
  128. #[inline]
  129. pub fn src_addr(&self) -> Address {
  130. let data = self.buffer.as_ref();
  131. Address::from_bytes(&data[field::SOURCE])
  132. }
  133. /// Return the EtherType field, without checking for 802.1Q.
  134. #[inline]
  135. pub fn ethertype(&self) -> EtherType {
  136. let data = self.buffer.as_ref();
  137. let raw = NetworkEndian::read_u16(&data[field::ETHERTYPE]);
  138. EtherType::from(raw)
  139. }
  140. }
  141. impl<'a, T: AsRef<[u8]> + ?Sized> Frame<&'a T> {
  142. /// Return a pointer to the payload, without checking for 802.1Q.
  143. #[inline]
  144. pub fn payload(&self) -> &'a [u8] {
  145. let data = self.buffer.as_ref();
  146. &data[field::PAYLOAD]
  147. }
  148. }
  149. impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
  150. /// Set the destination address field.
  151. #[inline]
  152. pub fn set_dst_addr(&mut self, value: Address) {
  153. let data = self.buffer.as_mut();
  154. data[field::DESTINATION].copy_from_slice(value.as_bytes())
  155. }
  156. /// Set the source address field.
  157. #[inline]
  158. pub fn set_src_addr(&mut self, value: Address) {
  159. let data = self.buffer.as_mut();
  160. data[field::SOURCE].copy_from_slice(value.as_bytes())
  161. }
  162. /// Set the EtherType field.
  163. #[inline]
  164. pub fn set_ethertype(&mut self, value: EtherType) {
  165. let data = self.buffer.as_mut();
  166. NetworkEndian::write_u16(&mut data[field::ETHERTYPE], value.into())
  167. }
  168. /// Return a mutable pointer to the payload.
  169. #[inline]
  170. pub fn payload_mut(&mut self) -> &mut [u8] {
  171. let data = self.buffer.as_mut();
  172. &mut data[field::PAYLOAD]
  173. }
  174. }
  175. impl<T: AsRef<[u8]>> AsRef<[u8]> for Frame<T> {
  176. fn as_ref(&self) -> &[u8] {
  177. self.buffer.as_ref()
  178. }
  179. }
  180. impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
  181. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  182. write!(
  183. f,
  184. "EthernetII src={} dst={} type={}",
  185. self.src_addr(),
  186. self.dst_addr(),
  187. self.ethertype()
  188. )
  189. }
  190. }
  191. use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
  192. impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
  193. fn pretty_print(
  194. buffer: &dyn AsRef<[u8]>,
  195. f: &mut fmt::Formatter,
  196. indent: &mut PrettyIndent,
  197. ) -> fmt::Result {
  198. let frame = match Frame::new_checked(buffer) {
  199. Err(err) => return write!(f, "{}({})", indent, err),
  200. Ok(frame) => frame,
  201. };
  202. write!(f, "{}{}", indent, frame)?;
  203. match frame.ethertype() {
  204. #[cfg(feature = "proto-ipv4")]
  205. EtherType::Arp => {
  206. indent.increase(f)?;
  207. super::ArpPacket::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  208. }
  209. #[cfg(feature = "proto-ipv4")]
  210. EtherType::Ipv4 => {
  211. indent.increase(f)?;
  212. super::Ipv4Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  213. }
  214. #[cfg(feature = "proto-ipv6")]
  215. EtherType::Ipv6 => {
  216. indent.increase(f)?;
  217. super::Ipv6Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  218. }
  219. _ => Ok(()),
  220. }
  221. }
  222. }
  223. /// A high-level representation of an Internet Protocol version 4 packet header.
  224. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  225. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  226. pub struct Repr {
  227. pub src_addr: Address,
  228. pub dst_addr: Address,
  229. pub ethertype: EtherType,
  230. }
  231. impl Repr {
  232. /// Parse an Ethernet II frame and return a high-level representation.
  233. pub fn parse<T: AsRef<[u8]> + ?Sized>(frame: &Frame<&T>) -> Result<Repr> {
  234. frame.check_len()?;
  235. Ok(Repr {
  236. src_addr: frame.src_addr(),
  237. dst_addr: frame.dst_addr(),
  238. ethertype: frame.ethertype(),
  239. })
  240. }
  241. /// Return the length of a header that will be emitted from this high-level representation.
  242. pub const fn buffer_len(&self) -> usize {
  243. HEADER_LEN
  244. }
  245. /// Emit a high-level representation into an Ethernet II frame.
  246. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, frame: &mut Frame<T>) {
  247. frame.set_src_addr(self.src_addr);
  248. frame.set_dst_addr(self.dst_addr);
  249. frame.set_ethertype(self.ethertype);
  250. }
  251. }
  252. #[cfg(test)]
  253. mod test {
  254. // Tests that are valid with any combination of
  255. // "proto-*" features.
  256. use super::*;
  257. #[test]
  258. fn test_broadcast() {
  259. assert!(Address::BROADCAST.is_broadcast());
  260. assert!(!Address::BROADCAST.is_unicast());
  261. assert!(Address::BROADCAST.is_multicast());
  262. assert!(Address::BROADCAST.is_local());
  263. }
  264. }
  265. #[cfg(test)]
  266. #[cfg(feature = "proto-ipv4")]
  267. mod test_ipv4 {
  268. // Tests that are valid only with "proto-ipv4"
  269. use super::*;
  270. static FRAME_BYTES: [u8; 64] = [
  271. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x08, 0x00, 0xaa,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  273. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  274. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  275. 0x00, 0x00, 0x00, 0xff,
  276. ];
  277. static PAYLOAD_BYTES: [u8; 50] = [
  278. 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  279. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  280. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  281. 0x00, 0x00, 0x00, 0x00, 0xff,
  282. ];
  283. #[test]
  284. fn test_deconstruct() {
  285. let frame = Frame::new_unchecked(&FRAME_BYTES[..]);
  286. assert_eq!(
  287. frame.dst_addr(),
  288. Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
  289. );
  290. assert_eq!(
  291. frame.src_addr(),
  292. Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])
  293. );
  294. assert_eq!(frame.ethertype(), EtherType::Ipv4);
  295. assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
  296. }
  297. #[test]
  298. fn test_construct() {
  299. let mut bytes = vec![0xa5; 64];
  300. let mut frame = Frame::new_unchecked(&mut bytes);
  301. frame.set_dst_addr(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  302. frame.set_src_addr(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  303. frame.set_ethertype(EtherType::Ipv4);
  304. frame.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
  305. assert_eq!(&frame.into_inner()[..], &FRAME_BYTES[..]);
  306. }
  307. }
  308. #[cfg(test)]
  309. #[cfg(feature = "proto-ipv6")]
  310. mod test_ipv6 {
  311. // Tests that are valid only with "proto-ipv6"
  312. use super::*;
  313. static FRAME_BYTES: [u8; 54] = [
  314. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x86, 0xdd, 0x60,
  315. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  316. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  317. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  318. ];
  319. static PAYLOAD_BYTES: [u8; 40] = [
  320. 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
  321. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  322. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  323. ];
  324. #[test]
  325. fn test_deconstruct() {
  326. let frame = Frame::new_unchecked(&FRAME_BYTES[..]);
  327. assert_eq!(
  328. frame.dst_addr(),
  329. Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
  330. );
  331. assert_eq!(
  332. frame.src_addr(),
  333. Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16])
  334. );
  335. assert_eq!(frame.ethertype(), EtherType::Ipv6);
  336. assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
  337. }
  338. #[test]
  339. fn test_construct() {
  340. let mut bytes = vec![0xa5; 54];
  341. let mut frame = Frame::new_unchecked(&mut bytes);
  342. frame.set_dst_addr(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  343. frame.set_src_addr(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  344. frame.set_ethertype(EtherType::Ipv6);
  345. assert_eq!(PAYLOAD_BYTES.len(), frame.payload_mut().len());
  346. frame.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
  347. assert_eq!(&frame.into_inner()[..], &FRAME_BYTES[..]);
  348. }
  349. }