1use crate::{err, ArpHardwareId, LinuxSllHeaderSlice, LinuxSllPacketType, LinuxSllProtocolType};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
5pub struct LinuxSllHeader {
6 pub packet_type: LinuxSllPacketType,
8 pub arp_hrd_type: ArpHardwareId,
10 pub sender_address_valid_length: u16,
12 pub sender_address: [u8; 8],
17 pub protocol_type: LinuxSllProtocolType,
19}
20
21impl LinuxSllHeader {
22 pub const LEN: usize = 16;
24
25 #[inline]
27 pub fn from_slice(
28 slice: &[u8],
29 ) -> Result<(LinuxSllHeader, &[u8]), err::linux_sll::HeaderSliceError> {
30 Ok((
31 LinuxSllHeaderSlice::from_slice(slice)?.to_header(),
32 &slice[LinuxSllHeader::LEN..],
33 ))
34 }
35
36 #[inline]
38 pub fn from_bytes(bytes: [u8; 16]) -> Result<LinuxSllHeader, err::linux_sll::HeaderError> {
39 let packet_type = LinuxSllPacketType::try_from(u16::from_be_bytes([bytes[0], bytes[1]]))?;
40 let arp_hrd_type = ArpHardwareId::from(u16::from_be_bytes([bytes[2], bytes[3]]));
41 let sender_address_valid_length = u16::from_be_bytes([bytes[4], bytes[5]]);
42 let sender_address = [
43 bytes[6], bytes[7], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13],
44 ];
45 let protocol_type = LinuxSllProtocolType::try_from((
46 arp_hrd_type,
47 u16::from_be_bytes([bytes[14], bytes[15]]),
48 ))?;
49
50 Ok(LinuxSllHeader {
51 packet_type,
52 arp_hrd_type,
53 sender_address_valid_length,
54 sender_address,
55 protocol_type,
56 })
57 }
58
59 #[cfg(feature = "std")]
61 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
62 pub fn read<T: std::io::Read + std::io::Seek + Sized>(
63 reader: &mut T,
64 ) -> Result<LinuxSllHeader, err::ReadError> {
65 let buffer = {
66 let mut buffer = [0; LinuxSllHeader::LEN];
67 reader.read_exact(&mut buffer)?;
68 buffer
69 };
70
71 Ok(
72 unsafe { LinuxSllHeaderSlice::from_slice_unchecked(&buffer) }.to_header(),
74 )
75 }
76
77 pub fn write_to_slice<'a>(
79 &self,
80 slice: &'a mut [u8],
81 ) -> Result<&'a mut [u8], err::SliceWriteSpaceError> {
82 if slice.len() < LinuxSllHeader::LEN {
84 Err(err::SliceWriteSpaceError {
85 required_len: LinuxSllHeader::LEN,
86 len: slice.len(),
87 layer: err::Layer::LinuxSllHeader,
88 layer_start_offset: 0,
89 })
90 } else {
91 slice[..LinuxSllHeader::LEN].copy_from_slice(&self.to_bytes());
92 Ok(&mut slice[LinuxSllHeader::LEN..])
93 }
94 }
95
96 #[cfg(feature = "std")]
98 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
99 #[inline]
100 pub fn write<T: std::io::Write + Sized>(&self, writer: &mut T) -> Result<(), std::io::Error> {
101 writer.write_all(&self.to_bytes())
102 }
103
104 #[inline]
106 pub fn header_len(&self) -> usize {
107 Self::LEN
108 }
109
110 #[inline]
113 pub fn to_bytes(&self) -> [u8; Self::LEN] {
114 let packet_type_be = u16::from(self.packet_type).to_be_bytes();
115 let arp_hrd_type_be = u16::from(self.arp_hrd_type).to_be_bytes();
116 let sender_address_valid_length_be = self.sender_address_valid_length.to_be_bytes();
117 let sender_address_be = self.sender_address;
118 let protocol_type_be = u16::from(self.protocol_type).to_be_bytes();
119
120 [
121 packet_type_be[0],
122 packet_type_be[1],
123 arp_hrd_type_be[0],
124 arp_hrd_type_be[1],
125 sender_address_valid_length_be[0],
126 sender_address_valid_length_be[1],
127 sender_address_be[0],
128 sender_address_be[1],
129 sender_address_be[2],
130 sender_address_be[3],
131 sender_address_be[4],
132 sender_address_be[5],
133 sender_address_be[6],
134 sender_address_be[7],
135 protocol_type_be[0],
136 protocol_type_be[1],
137 ]
138 }
139}
140
141#[cfg(test)]
142mod test {
143 use super::*;
144 use crate::{test_gens::*, LenSource};
145 use alloc::{format, vec::Vec};
146 use proptest::prelude::*;
147 use std::io::{Cursor, ErrorKind};
148
149 proptest! {
150 #[test]
151 fn from_slice(
152 input in linux_sll_any(),
153 dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
154 ) {
155 let mut buffer: Vec<u8> = Vec::with_capacity(LinuxSllHeader::LEN + dummy_data.len());
157 input.write(&mut buffer).unwrap();
158 buffer.extend(&dummy_data[..]);
159
160 {
162 let (result, rest) = LinuxSllHeader::from_slice(&buffer[..]).unwrap();
163 assert_eq!(input, result);
164 assert_eq!(&buffer[16..], rest);
165 }
166
167 for len in 0..=13 {
169 assert_eq!(
170 LinuxSllHeader::from_slice(&buffer[..len]).unwrap_err(),
171 err::linux_sll::HeaderSliceError::Len(err::LenError{
172 required_len: LinuxSllHeader::LEN,
173 len: len,
174 len_source: LenSource::Slice,
175 layer: err::Layer::LinuxSllHeader,
176 layer_start_offset: 0,
177 })
178 );
179 }
180 }
181 }
182
183 proptest! {
184 #[test]
185 fn from_bytes(input in linux_sll_any()) {
186 assert_eq!(
187 input,
188 LinuxSllHeader::from_bytes(input.to_bytes()).unwrap()
189 );
190 }
191 }
192
193 proptest! {
194 #[test]
195 fn read(
196 input in linux_sll_any(),
197 dummy_data in proptest::collection::vec(any::<u8>(), 0..20)
198 ) {
199 let mut buffer = Vec::with_capacity(LinuxSllHeader::LEN + dummy_data.len());
201 input.write(&mut buffer).unwrap();
202 buffer.extend(&dummy_data[..]);
203
204 {
206 let mut cursor = Cursor::new(&buffer);
207 let result = LinuxSllHeader::read(&mut cursor).unwrap();
208 assert_eq!(input, result);
209 assert_eq!(cursor.position(), u64::try_from(LinuxSllHeader::LEN).unwrap());
210 }
211
212 for len in 0..=13 {
214 let mut cursor = Cursor::new(&buffer[0..len]);
215 assert_eq!(
216 LinuxSllHeader::read(&mut cursor)
217 .unwrap_err()
218 .io().unwrap()
219 .kind(),
220 ErrorKind::UnexpectedEof
221 );
222 }
223 }
224 }
225
226 proptest! {
227 #[test]
228 fn write_to_slice(input in linux_sll_any()) {
229 {
231 let mut buffer: [u8;LinuxSllHeader::LEN] = [0;LinuxSllHeader::LEN];
232 input.write_to_slice(&mut buffer).unwrap();
233 assert_eq!(buffer, input.to_bytes());
234 }
235 for len in 0..14 {
237 let mut buffer: [u8;LinuxSllHeader::LEN] = [0;LinuxSllHeader::LEN];
238 assert_eq!(
239 err::SliceWriteSpaceError {
240 required_len: LinuxSllHeader::LEN,
241 len,
242 layer: err::Layer::LinuxSllHeader,
243 layer_start_offset: 0,
244 },
245 input.write_to_slice(&mut buffer[..len]).unwrap_err()
246 );
247 }
248 }
249 }
250
251 proptest! {
252 #[test]
253 fn write(input in linux_sll_any()) {
254 {
256 let mut buffer: Vec<u8> = Vec::with_capacity(LinuxSllHeader::LEN);
257 input.write(&mut buffer).unwrap();
258 assert_eq!(&buffer[..], &input.to_bytes());
259 }
260
261 for len in 0..8 {
263 let mut buffer = [0u8;8];
264 let mut writer = Cursor::new(&mut buffer[..len]);
265 assert!(input.write(&mut writer).is_err());
266 }
267 }
268 }
269
270 proptest! {
271 #[test]
272 fn header_len(input in linux_sll_any()) {
273 assert_eq!(input.header_len(), LinuxSllHeader::LEN);
274 }
275 }
276
277 proptest! {
278 #[test]
279 fn to_bytes(input in linux_sll_any()) {
280 let packet_type_be = u16::from(input.packet_type).to_be_bytes();
281 let arp_hrd_type_be = u16::from(input.arp_hrd_type).to_be_bytes();
282 let sender_address_valid_length_be = input.sender_address_valid_length.to_be_bytes();
283 let sender_address_be = input.sender_address;
284 let protocol_type_be = u16::from(input.protocol_type).to_be_bytes();
285
286 assert_eq!(
287 input.to_bytes(),
288 [
289 packet_type_be[0],
290 packet_type_be[1],
291 arp_hrd_type_be[0],
292 arp_hrd_type_be[1],
293 sender_address_valid_length_be[0],
294 sender_address_valid_length_be[1],
295 sender_address_be[0],
296 sender_address_be[1],
297 sender_address_be[2],
298 sender_address_be[3],
299 sender_address_be[4],
300 sender_address_be[5],
301 sender_address_be[6],
302 sender_address_be[7],
303 protocol_type_be[0],
304 protocol_type_be[1],
305 ]
306 );
307 }
308 }
309
310 proptest! {
311 #[test]
312 fn clone_eq(input in linux_sll_any()) {
313 assert_eq!(input, input.clone());
314 }
315 }
316
317 proptest! {
318 #[test]
319 fn dbg(input in linux_sll_any()) {
320 assert_eq!(
321 &format!(
322 "LinuxSllHeader {{ packet_type: {:?}, arp_hrd_type: {:?}, sender_address_valid_length: {:?}, sender_address: {:?}, protocol_type: {:?} }}",
323 input.packet_type,
324 input.arp_hrd_type,
325 input.sender_address_valid_length,
326 input.sender_address,
327 input.protocol_type,
328 ),
329 &format!("{:?}", input)
330 );
331 }
332 }
333}