arp.rs 14 KB

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