etherparse/net/
arp_packet_slice.rs1use super::{ArpHardwareId, ArpOperation};
2use crate::{
3 err::{Layer, LenError},
4 ArpPacket, EtherType, LenSource,
5};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct ArpPacketSlice<'a> {
10 slice: &'a [u8],
11}
12
13impl<'a> ArpPacketSlice<'a> {
14 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 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 core::slice::from_raw_parts(slice.as_ptr(), min_len)
47 },
48 })
49 }
50
51 #[inline]
53 pub fn slice(&self) -> &'a [u8] {
54 self.slice
55 }
56
57 #[inline]
59 pub const fn hw_addr_type(&self) -> ArpHardwareId {
60 ArpHardwareId(u16::from_be_bytes(
61 unsafe { [*self.slice.as_ptr(), *self.slice.as_ptr().add(1)] },
64 ))
65 }
66
67 #[inline]
69 pub const fn proto_addr_type(&self) -> EtherType {
70 EtherType(u16::from_be_bytes(
71 unsafe { [*self.slice.as_ptr().add(2), *self.slice.as_ptr().add(3)] },
74 ))
75 }
76
77 #[inline]
79 pub const fn hw_addr_size(&self) -> u8 {
80 unsafe { *self.slice.as_ptr().add(4) }
83 }
84
85 #[inline]
87 pub const fn proto_addr_size(&self) -> u8 {
88 unsafe { *self.slice.as_ptr().add(5) }
91 }
92
93 #[inline]
95 pub const fn operation(&self) -> ArpOperation {
96 ArpOperation(u16::from_be_bytes(
97 unsafe { [*self.slice.as_ptr().add(6), *self.slice.as_ptr().add(7)] },
100 ))
101 }
102
103 #[inline]
105 pub const fn sender_hw_addr(&self) -> &[u8] {
106 unsafe {
109 core::slice::from_raw_parts(self.slice.as_ptr().add(8), self.hw_addr_size() as usize)
110 }
111 }
112
113 #[inline]
115 pub const fn sender_protocol_addr(&self) -> &[u8] {
116 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 #[inline]
128 pub const fn target_hw_addr(&self) -> &[u8] {
129 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 #[inline]
143 pub const fn target_protocol_addr(&self) -> &[u8] {
144 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 #[inline]
158 pub fn to_packet(&self) -> ArpPacket {
159 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)]
177mod 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 let data = packet.to_bytes();
189
190 {
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 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}