arp.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. use byteorder::{ByteOrder, NetworkEndian};
  2. use core::fmt;
  3. use super::{Error, Result};
  4. pub use super::EthernetProtocol as Protocol;
  5. enum_with_unknown! {
  6. /// ARP hardware type.
  7. pub enum Hardware(u16) {
  8. Ethernet = 1
  9. }
  10. }
  11. enum_with_unknown! {
  12. /// ARP operation type.
  13. pub enum Operation(u16) {
  14. Request = 1,
  15. Reply = 2
  16. }
  17. }
  18. /// A read/write wrapper around an Address Resolution Protocol packet buffer.
  19. #[derive(Debug, PartialEq, Eq, Clone)]
  20. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  21. pub struct Packet<T: AsRef<[u8]>> {
  22. buffer: T,
  23. }
  24. mod field {
  25. #![allow(non_snake_case)]
  26. use crate::wire::field::*;
  27. pub const HTYPE: Field = 0..2;
  28. pub const PTYPE: Field = 2..4;
  29. pub const HLEN: usize = 4;
  30. pub const PLEN: usize = 5;
  31. pub const OPER: Field = 6..8;
  32. #[inline]
  33. pub const fn SHA(hardware_len: u8, _protocol_len: u8) -> Field {
  34. let start = OPER.end;
  35. start..(start + hardware_len as usize)
  36. }
  37. #[inline]
  38. pub const fn SPA(hardware_len: u8, protocol_len: u8) -> Field {
  39. let start = SHA(hardware_len, protocol_len).end;
  40. start..(start + protocol_len as usize)
  41. }
  42. #[inline]
  43. pub const fn THA(hardware_len: u8, protocol_len: u8) -> Field {
  44. let start = SPA(hardware_len, protocol_len).end;
  45. start..(start + hardware_len as usize)
  46. }
  47. #[inline]
  48. pub const fn TPA(hardware_len: u8, protocol_len: u8) -> Field {
  49. let start = THA(hardware_len, protocol_len).end;
  50. start..(start + protocol_len as usize)
  51. }
  52. }
  53. impl<T: AsRef<[u8]>> Packet<T> {
  54. /// Imbue a raw octet buffer with ARP packet structure.
  55. pub const fn new_unchecked(buffer: T) -> Packet<T> {
  56. Packet { buffer }
  57. }
  58. /// Shorthand for a combination of [new_unchecked] and [check_len].
  59. ///
  60. /// [new_unchecked]: #method.new_unchecked
  61. /// [check_len]: #method.check_len
  62. pub fn new_checked(buffer: T) -> Result<Packet<T>> {
  63. let packet = Self::new_unchecked(buffer);
  64. packet.check_len()?;
  65. Ok(packet)
  66. }
  67. /// Ensure that no accessor method will panic if called.
  68. /// Returns `Err(Error)` if the buffer is too short.
  69. ///
  70. /// The result of this check is invalidated by calling [set_hardware_len] or
  71. /// [set_protocol_len].
  72. ///
  73. /// [set_hardware_len]: #method.set_hardware_len
  74. /// [set_protocol_len]: #method.set_protocol_len
  75. #[allow(clippy::if_same_then_else)]
  76. pub fn check_len(&self) -> Result<()> {
  77. let len = self.buffer.as_ref().len();
  78. if len < field::OPER.end {
  79. Err(Error)
  80. } else if len < field::TPA(self.hardware_len(), self.protocol_len()).end {
  81. Err(Error)
  82. } else {
  83. Ok(())
  84. }
  85. }
  86. /// Consume the packet, returning the underlying buffer.
  87. pub fn into_inner(self) -> T {
  88. self.buffer
  89. }
  90. /// Return the hardware type field.
  91. #[inline]
  92. pub fn hardware_type(&self) -> Hardware {
  93. let data = self.buffer.as_ref();
  94. let raw = NetworkEndian::read_u16(&data[field::HTYPE]);
  95. Hardware::from(raw)
  96. }
  97. /// Return the protocol type field.
  98. #[inline]
  99. pub fn protocol_type(&self) -> Protocol {
  100. let data = self.buffer.as_ref();
  101. let raw = NetworkEndian::read_u16(&data[field::PTYPE]);
  102. Protocol::from(raw)
  103. }
  104. /// Return the hardware length field.
  105. #[inline]
  106. pub fn hardware_len(&self) -> u8 {
  107. let data = self.buffer.as_ref();
  108. data[field::HLEN]
  109. }
  110. /// Return the protocol length field.
  111. #[inline]
  112. pub fn protocol_len(&self) -> u8 {
  113. let data = self.buffer.as_ref();
  114. data[field::PLEN]
  115. }
  116. /// Return the operation field.
  117. #[inline]
  118. pub fn operation(&self) -> Operation {
  119. let data = self.buffer.as_ref();
  120. let raw = NetworkEndian::read_u16(&data[field::OPER]);
  121. Operation::from(raw)
  122. }
  123. /// Return the source hardware address field.
  124. pub fn source_hardware_addr(&self) -> &[u8] {
  125. let data = self.buffer.as_ref();
  126. &data[field::SHA(self.hardware_len(), self.protocol_len())]
  127. }
  128. /// Return the source protocol address field.
  129. pub fn source_protocol_addr(&self) -> &[u8] {
  130. let data = self.buffer.as_ref();
  131. &data[field::SPA(self.hardware_len(), self.protocol_len())]
  132. }
  133. /// Return the target hardware address field.
  134. pub fn target_hardware_addr(&self) -> &[u8] {
  135. let data = self.buffer.as_ref();
  136. &data[field::THA(self.hardware_len(), self.protocol_len())]
  137. }
  138. /// Return the target protocol address field.
  139. pub fn target_protocol_addr(&self) -> &[u8] {
  140. let data = self.buffer.as_ref();
  141. &data[field::TPA(self.hardware_len(), self.protocol_len())]
  142. }
  143. }
  144. impl<T: AsRef<[u8]> + AsMut<[u8]>> Packet<T> {
  145. /// Set the hardware type field.
  146. #[inline]
  147. pub fn set_hardware_type(&mut self, value: Hardware) {
  148. let data = self.buffer.as_mut();
  149. NetworkEndian::write_u16(&mut data[field::HTYPE], value.into())
  150. }
  151. /// Set the protocol type field.
  152. #[inline]
  153. pub fn set_protocol_type(&mut self, value: Protocol) {
  154. let data = self.buffer.as_mut();
  155. NetworkEndian::write_u16(&mut data[field::PTYPE], value.into())
  156. }
  157. /// Set the hardware length field.
  158. #[inline]
  159. pub fn set_hardware_len(&mut self, value: u8) {
  160. let data = self.buffer.as_mut();
  161. data[field::HLEN] = value
  162. }
  163. /// Set the protocol length field.
  164. #[inline]
  165. pub fn set_protocol_len(&mut self, value: u8) {
  166. let data = self.buffer.as_mut();
  167. data[field::PLEN] = value
  168. }
  169. /// Set the operation field.
  170. #[inline]
  171. pub fn set_operation(&mut self, value: Operation) {
  172. let data = self.buffer.as_mut();
  173. NetworkEndian::write_u16(&mut data[field::OPER], value.into())
  174. }
  175. /// Set the source hardware address field.
  176. ///
  177. /// # Panics
  178. /// The function panics if `value` is not `self.hardware_len()` long.
  179. pub fn set_source_hardware_addr(&mut self, value: &[u8]) {
  180. let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
  181. let data = self.buffer.as_mut();
  182. data[field::SHA(hardware_len, protocol_len)].copy_from_slice(value)
  183. }
  184. /// Set the source protocol address field.
  185. ///
  186. /// # Panics
  187. /// The function panics if `value` is not `self.protocol_len()` long.
  188. pub fn set_source_protocol_addr(&mut self, value: &[u8]) {
  189. let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
  190. let data = self.buffer.as_mut();
  191. data[field::SPA(hardware_len, protocol_len)].copy_from_slice(value)
  192. }
  193. /// Set the target hardware address field.
  194. ///
  195. /// # Panics
  196. /// The function panics if `value` is not `self.hardware_len()` long.
  197. pub fn set_target_hardware_addr(&mut self, value: &[u8]) {
  198. let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
  199. let data = self.buffer.as_mut();
  200. data[field::THA(hardware_len, protocol_len)].copy_from_slice(value)
  201. }
  202. /// Set the target protocol address field.
  203. ///
  204. /// # Panics
  205. /// The function panics if `value` is not `self.protocol_len()` long.
  206. pub fn set_target_protocol_addr(&mut self, value: &[u8]) {
  207. let (hardware_len, protocol_len) = (self.hardware_len(), self.protocol_len());
  208. let data = self.buffer.as_mut();
  209. data[field::TPA(hardware_len, protocol_len)].copy_from_slice(value)
  210. }
  211. }
  212. impl<T: AsRef<[u8]>> AsRef<[u8]> for Packet<T> {
  213. fn as_ref(&self) -> &[u8] {
  214. self.buffer.as_ref()
  215. }
  216. }
  217. use crate::wire::{EthernetAddress, Ipv4Address};
  218. /// A high-level representation of an Address Resolution Protocol packet.
  219. #[derive(Debug, PartialEq, Eq, Clone, Copy)]
  220. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  221. #[non_exhaustive]
  222. pub enum Repr {
  223. /// An Ethernet and IPv4 Address Resolution Protocol packet.
  224. EthernetIpv4 {
  225. operation: Operation,
  226. source_hardware_addr: EthernetAddress,
  227. source_protocol_addr: Ipv4Address,
  228. target_hardware_addr: EthernetAddress,
  229. target_protocol_addr: Ipv4Address,
  230. },
  231. }
  232. impl Repr {
  233. /// Parse an Address Resolution Protocol packet and return a high-level representation,
  234. /// or return `Err(Error)` if the packet is not recognized.
  235. pub fn parse<T: AsRef<[u8]>>(packet: &Packet<T>) -> Result<Repr> {
  236. match (
  237. packet.hardware_type(),
  238. packet.protocol_type(),
  239. packet.hardware_len(),
  240. packet.protocol_len(),
  241. ) {
  242. (Hardware::Ethernet, Protocol::Ipv4, 6, 4) => Ok(Repr::EthernetIpv4 {
  243. operation: packet.operation(),
  244. source_hardware_addr: EthernetAddress::from_bytes(packet.source_hardware_addr()),
  245. source_protocol_addr: Ipv4Address::from_bytes(packet.source_protocol_addr()),
  246. target_hardware_addr: EthernetAddress::from_bytes(packet.target_hardware_addr()),
  247. target_protocol_addr: Ipv4Address::from_bytes(packet.target_protocol_addr()),
  248. }),
  249. _ => Err(Error),
  250. }
  251. }
  252. /// Return the length of a packet that will be emitted from this high-level representation.
  253. pub const fn buffer_len(&self) -> usize {
  254. match *self {
  255. Repr::EthernetIpv4 { .. } => field::TPA(6, 4).end,
  256. }
  257. }
  258. /// Emit a high-level representation into an Address Resolution Protocol packet.
  259. pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, packet: &mut Packet<T>) {
  260. match *self {
  261. Repr::EthernetIpv4 {
  262. operation,
  263. source_hardware_addr,
  264. source_protocol_addr,
  265. target_hardware_addr,
  266. target_protocol_addr,
  267. } => {
  268. packet.set_hardware_type(Hardware::Ethernet);
  269. packet.set_protocol_type(Protocol::Ipv4);
  270. packet.set_hardware_len(6);
  271. packet.set_protocol_len(4);
  272. packet.set_operation(operation);
  273. packet.set_source_hardware_addr(source_hardware_addr.as_bytes());
  274. packet.set_source_protocol_addr(source_protocol_addr.as_bytes());
  275. packet.set_target_hardware_addr(target_hardware_addr.as_bytes());
  276. packet.set_target_protocol_addr(target_protocol_addr.as_bytes());
  277. }
  278. }
  279. }
  280. }
  281. impl<T: AsRef<[u8]>> fmt::Display for Packet<T> {
  282. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  283. match Repr::parse(self) {
  284. Ok(repr) => write!(f, "{}", repr),
  285. _ => {
  286. write!(f, "ARP (unrecognized)")?;
  287. write!(
  288. f,
  289. " htype={:?} ptype={:?} hlen={:?} plen={:?} op={:?}",
  290. self.hardware_type(),
  291. self.protocol_type(),
  292. self.hardware_len(),
  293. self.protocol_len(),
  294. self.operation()
  295. )?;
  296. write!(
  297. f,
  298. " sha={:?} spa={:?} tha={:?} tpa={:?}",
  299. self.source_hardware_addr(),
  300. self.source_protocol_addr(),
  301. self.target_hardware_addr(),
  302. self.target_protocol_addr()
  303. )?;
  304. Ok(())
  305. }
  306. }
  307. }
  308. }
  309. impl fmt::Display for Repr {
  310. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  311. match *self {
  312. Repr::EthernetIpv4 {
  313. operation,
  314. source_hardware_addr,
  315. source_protocol_addr,
  316. target_hardware_addr,
  317. target_protocol_addr,
  318. } => {
  319. write!(
  320. f,
  321. "ARP type=Ethernet+IPv4 src={}/{} tgt={}/{} op={:?}",
  322. source_hardware_addr,
  323. source_protocol_addr,
  324. target_hardware_addr,
  325. target_protocol_addr,
  326. operation
  327. )
  328. }
  329. }
  330. }
  331. }
  332. use crate::wire::pretty_print::{PrettyIndent, PrettyPrint};
  333. impl<T: AsRef<[u8]>> PrettyPrint for Packet<T> {
  334. fn pretty_print(
  335. buffer: &dyn AsRef<[u8]>,
  336. f: &mut fmt::Formatter,
  337. indent: &mut PrettyIndent,
  338. ) -> fmt::Result {
  339. match Packet::new_checked(buffer) {
  340. Err(err) => write!(f, "{}({})", indent, err),
  341. Ok(packet) => write!(f, "{}{}", indent, packet),
  342. }
  343. }
  344. }
  345. #[cfg(test)]
  346. mod test {
  347. use super::*;
  348. static PACKET_BYTES: [u8; 28] = [
  349. 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x21,
  350. 0x22, 0x23, 0x24, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x41, 0x42, 0x43, 0x44,
  351. ];
  352. #[test]
  353. fn test_deconstruct() {
  354. let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
  355. assert_eq!(packet.hardware_type(), Hardware::Ethernet);
  356. assert_eq!(packet.protocol_type(), Protocol::Ipv4);
  357. assert_eq!(packet.hardware_len(), 6);
  358. assert_eq!(packet.protocol_len(), 4);
  359. assert_eq!(packet.operation(), Operation::Request);
  360. assert_eq!(
  361. packet.source_hardware_addr(),
  362. &[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]
  363. );
  364. assert_eq!(packet.source_protocol_addr(), &[0x21, 0x22, 0x23, 0x24]);
  365. assert_eq!(
  366. packet.target_hardware_addr(),
  367. &[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]
  368. );
  369. assert_eq!(packet.target_protocol_addr(), &[0x41, 0x42, 0x43, 0x44]);
  370. }
  371. #[test]
  372. fn test_construct() {
  373. let mut bytes = vec![0xa5; 28];
  374. let mut packet = Packet::new_unchecked(&mut bytes);
  375. packet.set_hardware_type(Hardware::Ethernet);
  376. packet.set_protocol_type(Protocol::Ipv4);
  377. packet.set_hardware_len(6);
  378. packet.set_protocol_len(4);
  379. packet.set_operation(Operation::Request);
  380. packet.set_source_hardware_addr(&[0x11, 0x12, 0x13, 0x14, 0x15, 0x16]);
  381. packet.set_source_protocol_addr(&[0x21, 0x22, 0x23, 0x24]);
  382. packet.set_target_hardware_addr(&[0x31, 0x32, 0x33, 0x34, 0x35, 0x36]);
  383. packet.set_target_protocol_addr(&[0x41, 0x42, 0x43, 0x44]);
  384. assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
  385. }
  386. fn packet_repr() -> Repr {
  387. Repr::EthernetIpv4 {
  388. operation: Operation::Request,
  389. source_hardware_addr: EthernetAddress::from_bytes(&[
  390. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
  391. ]),
  392. source_protocol_addr: Ipv4Address::from_bytes(&[0x21, 0x22, 0x23, 0x24]),
  393. target_hardware_addr: EthernetAddress::from_bytes(&[
  394. 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
  395. ]),
  396. target_protocol_addr: Ipv4Address::from_bytes(&[0x41, 0x42, 0x43, 0x44]),
  397. }
  398. }
  399. #[test]
  400. fn test_parse() {
  401. let packet = Packet::new_unchecked(&PACKET_BYTES[..]);
  402. let repr = Repr::parse(&packet).unwrap();
  403. assert_eq!(repr, packet_repr());
  404. }
  405. #[test]
  406. fn test_emit() {
  407. let mut bytes = vec![0xa5; 28];
  408. let mut packet = Packet::new_unchecked(&mut bytes);
  409. packet_repr().emit(&mut packet);
  410. assert_eq!(&*packet.into_inner(), &PACKET_BYTES[..]);
  411. }
  412. }