1 use super::{ArpHardwareId, ArpOperation}; 2 use crate::{ 3 err::{Layer, LenError}, 4 ArpPacket, EtherType, LenSource, 5 }; 6 7 /// Slice containing an "Address Resolution Protocol" Packet. 8 #[derive(Clone, Debug, Eq, PartialEq)] 9 pub struct ArpPacketSlice<'a> { 10 slice: &'a [u8], 11 } 12 13 impl<'a> ArpPacketSlice<'a> { 14 /// Creates an `ArpPacketSlice` from a slice and verfies that the 15 /// given slice has enough data to contain an complete ARP packet. from_slice(slice: &'a [u8]) -> Result<ArpPacketSlice<'a>, LenError>16 pub fn from_slice(slice: &'a [u8]) -> Result<ArpPacketSlice<'a>, LenError> { 17 if slice.len() < 8 { 18 return Err(LenError { 19 required_len: 8, 20 len: slice.len(), 21 len_source: LenSource::Slice, 22 layer: Layer::Arp, 23 layer_start_offset: 0, 24 }); 25 } 26 27 // validate the rest length based on the hardware & protocol lengths 28 let hw_addr_size = unsafe { *slice.as_ptr().add(4) }; 29 let protocol_addr_size = unsafe { *slice.as_ptr().add(5) }; 30 let min_len = 8 + (hw_addr_size as usize) * 2 + (protocol_addr_size as usize) * 2; 31 32 if slice.len() < min_len { 33 return Err(LenError { 34 required_len: min_len, 35 len: slice.len(), 36 len_source: LenSource::ArpAddrLengths, 37 layer: Layer::Arp, 38 layer_start_offset: 0, 39 }); 40 } 41 42 Ok(Self { 43 slice: unsafe { 44 // SAFETY: Safe as slice was verified above to have a 45 // length of at least min_len. 46 core::slice::from_raw_parts(slice.as_ptr(), min_len) 47 }, 48 }) 49 } 50 51 /// Slice containing the ARP packet. 52 #[inline] slice(&self) -> &'a [u8]53 pub fn slice(&self) -> &'a [u8] { 54 self.slice 55 } 56 57 /// Network link protocol type (e.g. `ArpHardwareId::ETHERNET`). 58 #[inline] hw_addr_type(&self) -> ArpHardwareId59 pub const fn hw_addr_type(&self) -> ArpHardwareId { 60 ArpHardwareId(u16::from_be_bytes( 61 // SAFE: As the constructor verified the length 62 // of the slice to be at least 8. 63 unsafe { [*self.slice.as_ptr(), *self.slice.as_ptr().add(1)] }, 64 )) 65 } 66 67 /// Protocol for which the ARP request is intended (e.g. `EtherType::IPV4`). 68 #[inline] proto_addr_type(&self) -> EtherType69 pub const fn proto_addr_type(&self) -> EtherType { 70 EtherType(u16::from_be_bytes( 71 // SAFE: As the constructor verified the length 72 // of the slice to be at least 8. 73 unsafe { [*self.slice.as_ptr().add(2), *self.slice.as_ptr().add(3)] }, 74 )) 75 } 76 77 /// Length (in octets) of a hardware address (e.g. 6 for Ethernet). 78 #[inline] hw_addr_size(&self) -> u879 pub const fn hw_addr_size(&self) -> u8 { 80 // SAFE: As the constructor verified the length 81 // of the slice to be at least 8. 82 unsafe { *self.slice.as_ptr().add(4) } 83 } 84 85 /// Length (in octets) of internetwork addresses (e.g. 4 for IPv4 or 16 for IPv6). 86 #[inline] proto_addr_size(&self) -> u887 pub const fn proto_addr_size(&self) -> u8 { 88 // SAFE: As the constructor verified the length 89 // of the slice to be at least 8. 90 unsafe { *self.slice.as_ptr().add(5) } 91 } 92 93 /// Specifies the operation that the sender is performing 94 #[inline] operation(&self) -> ArpOperation95 pub const fn operation(&self) -> ArpOperation { 96 ArpOperation(u16::from_be_bytes( 97 // SAFE: As the constructor verified the length 98 // of the slice to be at least 8. 99 unsafe { [*self.slice.as_ptr().add(6), *self.slice.as_ptr().add(7)] }, 100 )) 101 } 102 103 /// Sender hardware address (e.g. MAC address). 104 #[inline] sender_hw_addr(&self) -> &[u8]105 pub const fn sender_hw_addr(&self) -> &[u8] { 106 // SAFETY: Safe as the constructor verfies the 107 // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2 108 unsafe { 109 core::slice::from_raw_parts(self.slice.as_ptr().add(8), self.hw_addr_size() as usize) 110 } 111 } 112 113 /// Sender protocol address (e.g. IPv4 address). 114 #[inline] sender_protocol_addr(&self) -> &[u8]115 pub const fn sender_protocol_addr(&self) -> &[u8] { 116 // SAFETY: Safe as the constructor verfies the 117 // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2 118 unsafe { 119 core::slice::from_raw_parts( 120 self.slice.as_ptr().add(8 + (self.hw_addr_size() as usize)), 121 self.proto_addr_size() as usize, 122 ) 123 } 124 } 125 126 /// Target hardware address (e.g. MAC address). 127 #[inline] target_hw_addr(&self) -> &[u8]128 pub const fn target_hw_addr(&self) -> &[u8] { 129 // SAFETY: Safe as the constructor verfies the 130 // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2 131 unsafe { 132 core::slice::from_raw_parts( 133 self.slice 134 .as_ptr() 135 .add(8 + (self.hw_addr_size() as usize) + (self.proto_addr_size() as usize)), 136 self.hw_addr_size() as usize, 137 ) 138 } 139 } 140 141 /// Buffer containing the target protocol address (e.g. IPv4 address).. 142 #[inline] target_protocol_addr(&self) -> &[u8]143 pub const fn target_protocol_addr(&self) -> &[u8] { 144 // SAFETY: Safe as the constructor verfies the 145 // the slice to be at least 8 + hw_addr_size*2 + protocol_addr_size*2 146 unsafe { 147 core::slice::from_raw_parts( 148 self.slice.as_ptr().add( 149 8 + (self.hw_addr_size() as usize) * 2 + (self.proto_addr_size() as usize), 150 ), 151 self.proto_addr_size() as usize, 152 ) 153 } 154 } 155 156 /// Decode fields and return results in an [`ArpPacket`]. 157 #[inline] to_packet(&self) -> ArpPacket158 pub fn to_packet(&self) -> ArpPacket { 159 // SAFETY: Safe as all preconditions of new unchecked 160 // are fullfilled by the fact that the on the wire packets already 161 // fullfill them. 162 unsafe { 163 ArpPacket::new_unchecked( 164 self.hw_addr_type(), 165 self.proto_addr_type(), 166 self.operation(), 167 self.sender_hw_addr(), 168 self.sender_protocol_addr(), 169 self.target_hw_addr(), 170 self.target_protocol_addr(), 171 ) 172 } 173 } 174 } 175 176 #[cfg(test)] 177 mod tests { 178 use super::*; 179 use crate::test_gens::*; 180 use proptest::prelude::*; 181 182 proptest! { 183 #[test] 184 fn from_slice_with_payload( 185 packet in arp_packet_any() 186 ) { 187 // build slice data 188 let data = packet.to_bytes(); 189 190 // happy path 191 { 192 let actual = ArpPacketSlice::from_slice(&data).unwrap(); 193 194 assert_eq!(actual.hw_addr_type(), packet.hw_addr_type); 195 assert_eq!(actual.proto_addr_type(), packet.proto_addr_type); 196 assert_eq!(actual.hw_addr_size(), packet.hw_addr_size()); 197 assert_eq!(actual.proto_addr_size(), packet.protocol_addr_size()); 198 assert_eq!(actual.operation(), packet.operation); 199 200 assert_eq!(actual.sender_hw_addr(), packet.sender_hw_addr()); 201 assert_eq!(actual.sender_protocol_addr(), packet.sender_protocol_addr()); 202 assert_eq!(actual.target_hw_addr(), packet.target_hw_addr()); 203 assert_eq!(actual.target_protocol_addr(), packet.target_protocol_addr()); 204 205 assert_eq!(&actual.to_packet(), &packet); 206 } 207 208 // length error 209 for len in 0..(8 + (packet.hw_addr_size() as usize)*2 + (packet.protocol_addr_size() as usize)*2) { 210 let err = ArpPacketSlice::from_slice(&data[..len]).unwrap_err(); 211 if len < 8 { 212 assert_eq!(err, LenError{ 213 required_len: 8, 214 len, 215 len_source: LenSource::Slice, 216 layer: Layer::Arp, 217 layer_start_offset: 0, 218 }); 219 } else { 220 assert_eq!(err, LenError{ 221 required_len: 8 + (packet.hw_addr_size() as usize)*2 + (packet.protocol_addr_size() as usize)*2, 222 len, 223 len_source: LenSource::ArpAddrLengths, 224 layer: Layer::Arp, 225 layer_start_offset: 0, 226 }); 227 } 228 } 229 } 230 } 231 } 232