ethernet.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. use core::fmt;
  2. use byteorder::{ByteOrder, NetworkEndian};
  3. use {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. pub struct Address(pub [u8; 6]);
  25. impl Address {
  26. /// The broadcast address.
  27. pub const BROADCAST: Address = Address([0xff; 6]);
  28. /// Construct an Ethernet address from a sequence of octets, in big-endian.
  29. ///
  30. /// # Panics
  31. /// The function panics if `data` is not six octets long.
  32. pub fn from_bytes(data: &[u8]) -> Address {
  33. let mut bytes = [0; 6];
  34. bytes.copy_from_slice(data);
  35. Address(bytes)
  36. }
  37. /// Return an Ethernet address as a sequence of octets, in big-endian.
  38. pub fn as_bytes(&self) -> &[u8] {
  39. &self.0
  40. }
  41. /// Query whether the address is an unicast address.
  42. pub fn is_unicast(&self) -> bool {
  43. !(self.is_broadcast() ||
  44. 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 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 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!(f, "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
  63. bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5])
  64. }
  65. }
  66. /// A read/write wrapper around an Ethernet II frame buffer.
  67. #[derive(Debug)]
  68. pub struct Frame<T: AsRef<[u8]>> {
  69. buffer: T
  70. }
  71. mod field {
  72. use wire::field::*;
  73. pub const DESTINATION: Field = 0..6;
  74. pub const SOURCE: Field = 6..12;
  75. pub const ETHERTYPE: Field = 12..14;
  76. pub const PAYLOAD: Rest = 14..;
  77. }
  78. impl<T: AsRef<[u8]>> Frame<T> {
  79. /// Imbue a raw octet buffer with Ethernet frame structure.
  80. pub fn new(buffer: T) -> Frame<T> {
  81. Frame { buffer }
  82. }
  83. /// Shorthand for a combination of [new] and [check_len].
  84. ///
  85. /// [new]: #method.new
  86. /// [check_len]: #method.check_len
  87. pub fn new_checked(buffer: T) -> Result<Frame<T>> {
  88. let packet = Self::new(buffer);
  89. packet.check_len()?;
  90. Ok(packet)
  91. }
  92. /// Ensure that no accessor method will panic if called.
  93. /// Returns `Err(Error::Truncated)` if the buffer is too short.
  94. pub fn check_len(&self) -> Result<()> {
  95. let len = self.buffer.as_ref().len();
  96. if len < field::PAYLOAD.start {
  97. Err(Error::Truncated)
  98. } else {
  99. Ok(())
  100. }
  101. }
  102. /// Consumes the frame, returning the underlying buffer.
  103. pub fn into_inner(self) -> T {
  104. self.buffer
  105. }
  106. /// Return the length of a frame header.
  107. pub fn header_len() -> usize {
  108. field::PAYLOAD.start
  109. }
  110. /// Return the length of a buffer required to hold a packet with the payload
  111. /// of a given length.
  112. pub fn buffer_len(payload_len: usize) -> usize {
  113. field::PAYLOAD.start + payload_len
  114. }
  115. /// Return the destination address field.
  116. #[inline]
  117. pub fn dst_addr(&self) -> Address {
  118. let data = self.buffer.as_ref();
  119. Address::from_bytes(&data[field::DESTINATION])
  120. }
  121. /// Return the source address field.
  122. #[inline]
  123. pub fn src_addr(&self) -> Address {
  124. let data = self.buffer.as_ref();
  125. Address::from_bytes(&data[field::SOURCE])
  126. }
  127. /// Return the EtherType field, without checking for 802.1Q.
  128. #[inline]
  129. pub fn ethertype(&self) -> EtherType {
  130. let data = self.buffer.as_ref();
  131. let raw = NetworkEndian::read_u16(&data[field::ETHERTYPE]);
  132. EtherType::from(raw)
  133. }
  134. }
  135. impl<'a, T: AsRef<[u8]> + ?Sized> Frame<&'a T> {
  136. /// Return a pointer to the payload, without checking for 802.1Q.
  137. #[inline]
  138. pub fn payload(&self) -> &'a [u8] {
  139. let data = self.buffer.as_ref();
  140. &data[field::PAYLOAD]
  141. }
  142. }
  143. impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
  144. /// Set the destination address field.
  145. #[inline]
  146. pub fn set_dst_addr(&mut self, value: Address) {
  147. let data = self.buffer.as_mut();
  148. data[field::DESTINATION].copy_from_slice(value.as_bytes())
  149. }
  150. /// Set the source address field.
  151. #[inline]
  152. pub fn set_src_addr(&mut self, value: Address) {
  153. let data = self.buffer.as_mut();
  154. data[field::SOURCE].copy_from_slice(value.as_bytes())
  155. }
  156. /// Set the EtherType field.
  157. #[inline]
  158. pub fn set_ethertype(&mut self, value: EtherType) {
  159. let data = self.buffer.as_mut();
  160. NetworkEndian::write_u16(&mut data[field::ETHERTYPE], value.into())
  161. }
  162. /// Return a mutable pointer to the payload.
  163. #[inline]
  164. pub fn payload_mut(&mut self) -> &mut [u8] {
  165. let data = self.buffer.as_mut();
  166. &mut data[field::PAYLOAD]
  167. }
  168. }
  169. impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
  170. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  171. write!(f, "EthernetII src={} dst={} type={}",
  172. self.src_addr(), self.dst_addr(), self.ethertype())
  173. }
  174. }
  175. use super::pretty_print::{PrettyPrint, PrettyIndent};
  176. impl<T: AsRef<[u8]>> PrettyPrint for Frame<T> {
  177. fn pretty_print(buffer: &AsRef<[u8]>, f: &mut fmt::Formatter,
  178. indent: &mut PrettyIndent) -> fmt::Result {
  179. let frame = match Frame::new_checked(buffer) {
  180. Err(err) => return write!(f, "{}({})", indent, err),
  181. Ok(frame) => frame
  182. };
  183. write!(f, "{}{}", indent, frame)?;
  184. match frame.ethertype() {
  185. #[cfg(feature = "proto-ipv4")]
  186. EtherType::Arp => {
  187. indent.increase(f)?;
  188. super::ArpPacket::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  189. }
  190. #[cfg(feature = "proto-ipv4")]
  191. EtherType::Ipv4 => {
  192. indent.increase(f)?;
  193. super::Ipv4Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  194. }
  195. #[cfg(feature = "proto-ipv6")]
  196. EtherType::Ipv6 => {
  197. indent.increase(f)?;
  198. super::Ipv6Packet::<&[u8]>::pretty_print(&frame.payload(), f, indent)
  199. }
  200. _ => Ok(())
  201. }
  202. }
  203. }
  204. #[cfg(test)]
  205. mod test {
  206. // Tests that are valid with any combination of
  207. // "proto-*" features.
  208. use super::*;
  209. #[test]
  210. fn test_broadcast() {
  211. assert!(Address::BROADCAST.is_broadcast());
  212. assert!(!Address::BROADCAST.is_unicast());
  213. assert!(Address::BROADCAST.is_multicast());
  214. assert!(Address::BROADCAST.is_local());
  215. }
  216. }
  217. #[cfg(test)]
  218. #[cfg(feature = "proto-ipv4")]
  219. mod test_ipv4 {
  220. // Tests that are valid only with "proto-ipv4"
  221. use super::*;
  222. static FRAME_BYTES: [u8; 64] =
  223. [0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  224. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
  225. 0x08, 0x00,
  226. 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  227. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  228. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  229. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  231. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  232. 0x00, 0xff];
  233. static PAYLOAD_BYTES: [u8; 50] =
  234. [0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  235. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  236. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  238. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  239. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  240. 0x00, 0xff];
  241. #[test]
  242. fn test_deconstruct() {
  243. let frame = Frame::new(&FRAME_BYTES[..]);
  244. assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  245. assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  246. assert_eq!(frame.ethertype(), EtherType::Ipv4);
  247. assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
  248. }
  249. #[test]
  250. fn test_construct() {
  251. let mut bytes = vec![0xa5; 64];
  252. let mut frame = Frame::new(&mut bytes);
  253. frame.set_dst_addr(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  254. frame.set_src_addr(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  255. frame.set_ethertype(EtherType::Ipv4);
  256. frame.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
  257. assert_eq!(&frame.into_inner()[..], &FRAME_BYTES[..]);
  258. }
  259. }
  260. #[cfg(test)]
  261. #[cfg(feature = "proto-ipv6")]
  262. mod test_ipv6 {
  263. // Tests that are valid only with "proto-ipv6"
  264. use super::*;
  265. static FRAME_BYTES: [u8; 54] =
  266. [0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  267. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
  268. 0x86, 0xdd,
  269. 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  270. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  271. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  273. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];
  274. static PAYLOAD_BYTES: [u8; 40] =
  275. [0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  278. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  279. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01];
  280. #[test]
  281. fn test_deconstruct() {
  282. let frame = Frame::new(&FRAME_BYTES[..]);
  283. assert_eq!(frame.dst_addr(), Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  284. assert_eq!(frame.src_addr(), Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  285. assert_eq!(frame.ethertype(), EtherType::Ipv6);
  286. assert_eq!(frame.payload(), &PAYLOAD_BYTES[..]);
  287. }
  288. #[test]
  289. fn test_construct() {
  290. let mut bytes = vec![0xa5; 54];
  291. let mut frame = Frame::new(&mut bytes);
  292. frame.set_dst_addr(Address([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
  293. frame.set_src_addr(Address([0x11, 0x12, 0x13, 0x14, 0x15, 0x16]));
  294. frame.set_ethertype(EtherType::Ipv6);
  295. assert_eq!(PAYLOAD_BYTES.len(), frame.payload_mut().len());
  296. frame.payload_mut().copy_from_slice(&PAYLOAD_BYTES[..]);
  297. assert_eq!(&frame.into_inner()[..], &FRAME_BYTES[..]);
  298. }
  299. }