1 use core::fmt;
2 
3 use byteorder::{ByteOrder, LittleEndian};
4 
5 use super::{Error, Result};
6 use crate::wire::ipv6::Address as Ipv6Address;
7 
8 enum_with_unknown! {
9     /// IEEE 802.15.4 frame type.
10     pub enum FrameType(u8) {
11         Beacon = 0b000,
12         Data = 0b001,
13         Acknowledgement = 0b010,
14         MacCommand = 0b011,
15         Multipurpose = 0b101,
16         FragmentOrFrak = 0b110,
17         Extended = 0b111,
18     }
19 }
20 
21 impl fmt::Display for FrameType {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result22     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
23         match self {
24             FrameType::Beacon => write!(f, "Beacon"),
25             FrameType::Data => write!(f, "Data"),
26             FrameType::Acknowledgement => write!(f, "Ack"),
27             FrameType::MacCommand => write!(f, "MAC command"),
28             FrameType::Multipurpose => write!(f, "Multipurpose"),
29             FrameType::FragmentOrFrak => write!(f, "FragmentOrFrak"),
30             FrameType::Extended => write!(f, "Extended"),
31             FrameType::Unknown(id) => write!(f, "0b{id:04b}"),
32         }
33     }
34 }
35 enum_with_unknown! {
36     /// IEEE 802.15.4 addressing mode for destination and source addresses.
37     pub enum AddressingMode(u8) {
38         Absent    = 0b00,
39         Short     = 0b10,
40         Extended  = 0b11,
41     }
42 }
43 
44 impl AddressingMode {
45     /// Return the size in octets of the address.
size(&self) -> usize46     const fn size(&self) -> usize {
47         match self {
48             AddressingMode::Absent => 0,
49             AddressingMode::Short => 2,
50             AddressingMode::Extended => 8,
51             AddressingMode::Unknown(_) => 0, // TODO(thvdveld): what do we need to here?
52         }
53     }
54 }
55 
56 impl fmt::Display for AddressingMode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result57     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58         match self {
59             AddressingMode::Absent => write!(f, "Absent"),
60             AddressingMode::Short => write!(f, "Short"),
61             AddressingMode::Extended => write!(f, "Extended"),
62             AddressingMode::Unknown(id) => write!(f, "0b{id:04b}"),
63         }
64     }
65 }
66 
67 /// A IEEE 802.15.4 PAN.
68 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
69 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
70 pub struct Pan(pub u16);
71 
72 impl Pan {
73     pub const BROADCAST: Self = Self(0xffff);
74 
75     /// Return the PAN ID as bytes.
as_bytes(&self) -> [u8; 2]76     pub fn as_bytes(&self) -> [u8; 2] {
77         let mut pan = [0u8; 2];
78         LittleEndian::write_u16(&mut pan, self.0);
79         pan
80     }
81 }
82 
83 /// A IEEE 802.15.4 address.
84 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
85 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
86 pub enum Address {
87     Absent,
88     Short([u8; 2]),
89     Extended([u8; 8]),
90 }
91 
92 #[cfg(test)]
93 impl Default for Address {
default() -> Self94     fn default() -> Self {
95         Address::Extended([0u8; 8])
96     }
97 }
98 
99 impl Address {
100     /// The broadcast address.
101     pub const BROADCAST: Address = Address::Short([0xff; 2]);
102 
103     /// Query whether the address is an unicast address.
is_unicast(&self) -> bool104     pub fn is_unicast(&self) -> bool {
105         !self.is_broadcast()
106     }
107 
108     /// Query whether this address is the broadcast address.
is_broadcast(&self) -> bool109     pub fn is_broadcast(&self) -> bool {
110         *self == Self::BROADCAST
111     }
112 
short_from_bytes(a: [u8; 2]) -> Self113     const fn short_from_bytes(a: [u8; 2]) -> Self {
114         Self::Short(a)
115     }
116 
extended_from_bytes(a: [u8; 8]) -> Self117     const fn extended_from_bytes(a: [u8; 8]) -> Self {
118         Self::Extended(a)
119     }
120 
from_bytes(a: &[u8]) -> Self121     pub fn from_bytes(a: &[u8]) -> Self {
122         if a.len() == 2 {
123             let mut b = [0u8; 2];
124             b.copy_from_slice(a);
125             Address::Short(b)
126         } else if a.len() == 8 {
127             let mut b = [0u8; 8];
128             b.copy_from_slice(a);
129             Address::Extended(b)
130         } else {
131             panic!("Not an IEEE802.15.4 address");
132         }
133     }
134 
as_bytes(&self) -> &[u8]135     pub const fn as_bytes(&self) -> &[u8] {
136         match self {
137             Address::Absent => &[],
138             Address::Short(value) => value,
139             Address::Extended(value) => value,
140         }
141     }
142 
143     /// Convert the extended address to an Extended Unique Identifier (EUI-64)
as_eui_64(&self) -> Option<[u8; 8]>144     pub fn as_eui_64(&self) -> Option<[u8; 8]> {
145         match self {
146             Address::Absent | Address::Short(_) => None,
147             Address::Extended(value) => {
148                 let mut bytes = [0; 8];
149                 bytes.copy_from_slice(&value[..]);
150 
151                 bytes[0] ^= 1 << 1;
152 
153                 Some(bytes)
154             }
155         }
156     }
157 
158     /// Convert an extended address to a link-local IPv6 address using the EUI-64 format from
159     /// RFC2464.
as_link_local_address(&self) -> Option<Ipv6Address>160     pub fn as_link_local_address(&self) -> Option<Ipv6Address> {
161         let mut bytes = [0; 16];
162         bytes[0] = 0xfe;
163         bytes[1] = 0x80;
164         bytes[8..].copy_from_slice(&self.as_eui_64()?);
165 
166         Some(Ipv6Address::from_bytes(&bytes))
167     }
168 }
169 
170 impl fmt::Display for Address {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result171     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
172         match self {
173             Self::Absent => write!(f, "not-present"),
174             Self::Short(bytes) => write!(f, "{:02x}-{:02x}", bytes[0], bytes[1]),
175             Self::Extended(bytes) => write!(
176                 f,
177                 "{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}-{:02x}",
178                 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]
179             ),
180         }
181     }
182 }
183 
184 enum_with_unknown! {
185     /// IEEE 802.15.4 addressing mode for destination and source addresses.
186     pub enum FrameVersion(u8) {
187         Ieee802154_2003 = 0b00,
188         Ieee802154_2006 = 0b01,
189         Ieee802154 = 0b10,
190     }
191 }
192 
193 /// A read/write wrapper around an IEEE 802.15.4 frame buffer.
194 #[derive(Debug, Clone)]
195 pub struct Frame<T: AsRef<[u8]>> {
196     buffer: T,
197 }
198 
199 mod field {
200     use crate::wire::field::*;
201 
202     pub const FRAMECONTROL: Field = 0..2;
203     pub const SEQUENCE_NUMBER: usize = 2;
204     pub const ADDRESSING: Rest = 3..;
205 }
206 
207 macro_rules! fc_bit_field {
208     ($field:ident, $bit:literal) => {
209         #[inline]
210         pub fn $field(&self) -> bool {
211             let data = self.buffer.as_ref();
212             let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
213 
214             ((raw >> $bit) & 0b1) == 0b1
215         }
216     };
217 }
218 
219 macro_rules! set_fc_bit_field {
220     ($field:ident, $bit:literal) => {
221         #[inline]
222         pub fn $field(&mut self, val: bool) {
223             let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
224             let mut raw = LittleEndian::read_u16(data);
225             raw |= ((val as u16) << $bit);
226 
227             data.copy_from_slice(&raw.to_le_bytes());
228         }
229     };
230 }
231 
232 impl<T: AsRef<[u8]>> Frame<T> {
233     /// Input a raw octet buffer with Ethernet frame structure.
new_unchecked(buffer: T) -> Frame<T>234     pub const fn new_unchecked(buffer: T) -> Frame<T> {
235         Frame { buffer }
236     }
237 
238     /// Shorthand for a combination of [new_unchecked] and [check_len].
239     ///
240     /// [new_unchecked]: #method.new_unchecked
241     /// [check_len]: #method.check_len
new_checked(buffer: T) -> Result<Frame<T>>242     pub fn new_checked(buffer: T) -> Result<Frame<T>> {
243         let packet = Self::new_unchecked(buffer);
244         packet.check_len()?;
245 
246         if matches!(packet.dst_addressing_mode(), AddressingMode::Unknown(_)) {
247             return Err(Error);
248         }
249 
250         if matches!(packet.src_addressing_mode(), AddressingMode::Unknown(_)) {
251             return Err(Error);
252         }
253 
254         Ok(packet)
255     }
256 
257     /// Ensure that no accessor method will panic if called.
258     /// Returns `Err(Error)` if the buffer is too short.
check_len(&self) -> Result<()>259     pub fn check_len(&self) -> Result<()> {
260         // We need at least 3 bytes
261         if self.buffer.as_ref().len() < 3 {
262             return Err(Error);
263         }
264 
265         let mut offset = field::ADDRESSING.start + 2;
266 
267         // Calculate the size of the addressing field.
268         offset += self.dst_addressing_mode().size();
269         offset += self.src_addressing_mode().size();
270 
271         if !self.pan_id_compression() {
272             offset += 2;
273         }
274 
275         if offset > self.buffer.as_ref().len() {
276             return Err(Error);
277         }
278 
279         Ok(())
280     }
281 
282     /// Consumes the frame, returning the underlying buffer.
into_inner(self) -> T283     pub fn into_inner(self) -> T {
284         self.buffer
285     }
286 
287     /// Return the FrameType field.
288     #[inline]
frame_type(&self) -> FrameType289     pub fn frame_type(&self) -> FrameType {
290         let data = self.buffer.as_ref();
291         let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
292         let ft = (raw & 0b11) as u8;
293         FrameType::from(ft)
294     }
295 
296     fc_bit_field!(security_enabled, 3);
297     fc_bit_field!(frame_pending, 4);
298     fc_bit_field!(ack_request, 5);
299     fc_bit_field!(pan_id_compression, 6);
300 
301     fc_bit_field!(sequence_number_suppression, 8);
302     fc_bit_field!(ie_present, 9);
303 
304     /// Return the destination addressing mode.
305     #[inline]
dst_addressing_mode(&self) -> AddressingMode306     pub fn dst_addressing_mode(&self) -> AddressingMode {
307         let data = self.buffer.as_ref();
308         let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
309         let am = ((raw >> 10) & 0b11) as u8;
310         AddressingMode::from(am)
311     }
312 
313     /// Return the frame version.
314     #[inline]
frame_version(&self) -> FrameVersion315     pub fn frame_version(&self) -> FrameVersion {
316         let data = self.buffer.as_ref();
317         let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
318         let fv = ((raw >> 12) & 0b11) as u8;
319         FrameVersion::from(fv)
320     }
321 
322     /// Return the source addressing mode.
323     #[inline]
src_addressing_mode(&self) -> AddressingMode324     pub fn src_addressing_mode(&self) -> AddressingMode {
325         let data = self.buffer.as_ref();
326         let raw = LittleEndian::read_u16(&data[field::FRAMECONTROL]);
327         let am = ((raw >> 14) & 0b11) as u8;
328         AddressingMode::from(am)
329     }
330 
331     /// Return the sequence number of the frame.
332     #[inline]
sequence_number(&self) -> Option<u8>333     pub fn sequence_number(&self) -> Option<u8> {
334         match self.frame_type() {
335             FrameType::Beacon
336             | FrameType::Data
337             | FrameType::Acknowledgement
338             | FrameType::MacCommand
339             | FrameType::Multipurpose => {
340                 let data = self.buffer.as_ref();
341                 let raw = data[field::SEQUENCE_NUMBER];
342                 Some(raw)
343             }
344             FrameType::Extended | FrameType::FragmentOrFrak | FrameType::Unknown(_) => None,
345         }
346     }
347 
348     /// Return the addressing fields.
349     #[inline]
addressing_fields(&self) -> Option<&[u8]>350     fn addressing_fields(&self) -> Option<&[u8]> {
351         match self.frame_type() {
352             FrameType::Beacon
353             | FrameType::Data
354             | FrameType::MacCommand
355             | FrameType::Multipurpose => (),
356             FrameType::Acknowledgement if self.frame_version() == FrameVersion::Ieee802154 => (),
357             FrameType::Acknowledgement
358             | FrameType::Extended
359             | FrameType::FragmentOrFrak
360             | FrameType::Unknown(_) => return None,
361         }
362 
363         let mut offset = 2;
364 
365         // Calculate the size of the addressing field.
366         offset += self.dst_addressing_mode().size();
367         offset += self.src_addressing_mode().size();
368 
369         if !self.pan_id_compression() {
370             offset += 2;
371         }
372 
373         Some(&self.buffer.as_ref()[field::ADDRESSING][..offset])
374     }
375 
376     /// Return the destination PAN field.
377     #[inline]
dst_pan_id(&self) -> Option<Pan>378     pub fn dst_pan_id(&self) -> Option<Pan> {
379         let addressing_fields = self.addressing_fields()?;
380         match self.dst_addressing_mode() {
381             AddressingMode::Absent => None,
382             AddressingMode::Short | AddressingMode::Extended => {
383                 Some(Pan(LittleEndian::read_u16(&addressing_fields[0..2])))
384             }
385             AddressingMode::Unknown(_) => None,
386         }
387     }
388 
389     /// Return the destination address field.
390     #[inline]
dst_addr(&self) -> Option<Address>391     pub fn dst_addr(&self) -> Option<Address> {
392         let addressing_fields = self.addressing_fields()?;
393         match self.dst_addressing_mode() {
394             AddressingMode::Absent => Some(Address::Absent),
395             AddressingMode::Short => {
396                 let mut raw = [0u8; 2];
397                 raw.clone_from_slice(&addressing_fields[2..4]);
398                 raw.reverse();
399                 Some(Address::short_from_bytes(raw))
400             }
401             AddressingMode::Extended => {
402                 let mut raw = [0u8; 8];
403                 raw.clone_from_slice(&addressing_fields[2..10]);
404                 raw.reverse();
405                 Some(Address::extended_from_bytes(raw))
406             }
407             AddressingMode::Unknown(_) => None,
408         }
409     }
410 
411     /// Return the destination PAN field.
412     #[inline]
src_pan_id(&self) -> Option<Pan>413     pub fn src_pan_id(&self) -> Option<Pan> {
414         if self.pan_id_compression() {
415             return None;
416         }
417 
418         let addressing_fields = self.addressing_fields()?;
419         let offset = self.dst_addressing_mode().size() + 2;
420 
421         match self.src_addressing_mode() {
422             AddressingMode::Absent => None,
423             AddressingMode::Short | AddressingMode::Extended => Some(Pan(LittleEndian::read_u16(
424                 &addressing_fields[offset..offset + 2],
425             ))),
426             AddressingMode::Unknown(_) => None,
427         }
428     }
429 
430     /// Return the source address field.
431     #[inline]
src_addr(&self) -> Option<Address>432     pub fn src_addr(&self) -> Option<Address> {
433         let addressing_fields = self.addressing_fields()?;
434         let mut offset = match self.dst_addressing_mode() {
435             AddressingMode::Absent => 0,
436             AddressingMode::Short => 2,
437             AddressingMode::Extended => 8,
438             _ => return None, // TODO(thvdveld): what do we do here?
439         } + 2;
440 
441         if !self.pan_id_compression() {
442             offset += 2;
443         }
444 
445         match self.src_addressing_mode() {
446             AddressingMode::Absent => Some(Address::Absent),
447             AddressingMode::Short => {
448                 let mut raw = [0u8; 2];
449                 raw.clone_from_slice(&addressing_fields[offset..offset + 2]);
450                 raw.reverse();
451                 Some(Address::short_from_bytes(raw))
452             }
453             AddressingMode::Extended => {
454                 let mut raw = [0u8; 8];
455                 raw.clone_from_slice(&addressing_fields[offset..offset + 8]);
456                 raw.reverse();
457                 Some(Address::extended_from_bytes(raw))
458             }
459             AddressingMode::Unknown(_) => None,
460         }
461     }
462 
463     /// Return the index where the auxiliary security header starts.
aux_security_header_start(&self) -> usize464     fn aux_security_header_start(&self) -> usize {
465         // We start with 3, because 2 bytes for frame control and the sequence number.
466         let mut index = 3;
467         index += self.addressing_fields().unwrap().len();
468         index
469     }
470 
471     /// Return the index where the payload starts.
payload_start(&self) -> usize472     fn payload_start(&self) -> usize {
473         let mut index = self.aux_security_header_start();
474 
475         if self.security_enabled() {
476             // We add 5 because 1 byte for control bits and 4 bytes for frame counter.
477             index += 5;
478             index += if let Some(len) = self.key_identifier_length() {
479                 len as usize
480             } else {
481                 0
482             };
483         }
484 
485         index
486     }
487 
488     /// Return the length of the key identifier field.
key_identifier_length(&self) -> Option<u8>489     fn key_identifier_length(&self) -> Option<u8> {
490         Some(match self.key_identifier_mode() {
491             0 => 0,
492             1 => 1,
493             2 => 5,
494             3 => 9,
495             _ => return None,
496         })
497     }
498 
499     /// Return the security level of the auxiliary security header.
security_level(&self) -> u8500     pub fn security_level(&self) -> u8 {
501         let index = self.aux_security_header_start();
502         let b = self.buffer.as_ref()[index..][0];
503         b & 0b111
504     }
505 
506     /// Return the key identifier mode used by the auxiliary security header.
key_identifier_mode(&self) -> u8507     pub fn key_identifier_mode(&self) -> u8 {
508         let index = self.aux_security_header_start();
509         let b = self.buffer.as_ref()[index..][0];
510         (b >> 3) & 0b11
511     }
512 
513     /// Return the frame counter field.
frame_counter(&self) -> u32514     pub fn frame_counter(&self) -> u32 {
515         let index = self.aux_security_header_start();
516         let b = &self.buffer.as_ref()[index..];
517         LittleEndian::read_u32(&b[1..1 + 4])
518     }
519 
520     /// Return the Key Identifier field.
key_identifier(&self) -> &[u8]521     fn key_identifier(&self) -> &[u8] {
522         let index = self.aux_security_header_start();
523         let b = &self.buffer.as_ref()[index..];
524         let length = if let Some(len) = self.key_identifier_length() {
525             len as usize
526         } else {
527             0
528         };
529         &b[5..][..length]
530     }
531 
532     /// Return the Key Source field.
key_source(&self) -> Option<&[u8]>533     pub fn key_source(&self) -> Option<&[u8]> {
534         let ki = self.key_identifier();
535         let len = ki.len();
536         if len > 1 {
537             Some(&ki[..len - 1])
538         } else {
539             None
540         }
541     }
542 
543     /// Return the Key Index field.
key_index(&self) -> Option<u8>544     pub fn key_index(&self) -> Option<u8> {
545         let ki = self.key_identifier();
546         let len = ki.len();
547 
548         if len > 0 {
549             Some(ki[len - 1])
550         } else {
551             None
552         }
553     }
554 
555     /// Return the Message Integrity Code (MIC).
message_integrity_code(&self) -> Option<&[u8]>556     pub fn message_integrity_code(&self) -> Option<&[u8]> {
557         let mic_len = match self.security_level() {
558             0 | 4 => return None,
559             1 | 5 => 4,
560             2 | 6 => 8,
561             3 | 7 => 16,
562             _ => panic!(),
563         };
564 
565         let data = &self.buffer.as_ref();
566         let len = data.len();
567 
568         Some(&data[len - mic_len..])
569     }
570 
571     /// Return the MAC header.
mac_header(&self) -> &[u8]572     pub fn mac_header(&self) -> &[u8] {
573         let data = &self.buffer.as_ref();
574         &data[..self.payload_start()]
575     }
576 }
577 
578 impl<'a, T: AsRef<[u8]> + ?Sized> Frame<&'a T> {
579     /// Return a pointer to the payload.
580     #[inline]
payload(&self) -> Option<&'a [u8]>581     pub fn payload(&self) -> Option<&'a [u8]> {
582         match self.frame_type() {
583             FrameType::Data => {
584                 let index = self.payload_start();
585                 let data = &self.buffer.as_ref();
586 
587                 Some(&data[index..])
588             }
589             _ => None,
590         }
591     }
592 }
593 
594 impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
595     /// Set the frame type.
596     #[inline]
set_frame_type(&mut self, frame_type: FrameType)597     pub fn set_frame_type(&mut self, frame_type: FrameType) {
598         let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
599         let mut raw = LittleEndian::read_u16(data);
600 
601         raw = (raw & !(0b111)) | (u8::from(frame_type) as u16 & 0b111);
602         data.copy_from_slice(&raw.to_le_bytes());
603     }
604 
605     set_fc_bit_field!(set_security_enabled, 3);
606     set_fc_bit_field!(set_frame_pending, 4);
607     set_fc_bit_field!(set_ack_request, 5);
608     set_fc_bit_field!(set_pan_id_compression, 6);
609 
610     /// Set the frame version.
611     #[inline]
set_frame_version(&mut self, version: FrameVersion)612     pub fn set_frame_version(&mut self, version: FrameVersion) {
613         let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
614         let mut raw = LittleEndian::read_u16(data);
615 
616         raw = (raw & !(0b11 << 12)) | ((u8::from(version) as u16 & 0b11) << 12);
617         data.copy_from_slice(&raw.to_le_bytes());
618     }
619 
620     /// Set the frame sequence number.
621     #[inline]
set_sequence_number(&mut self, value: u8)622     pub fn set_sequence_number(&mut self, value: u8) {
623         let data = self.buffer.as_mut();
624         data[field::SEQUENCE_NUMBER] = value;
625     }
626 
627     /// Set the destination PAN ID.
628     #[inline]
set_dst_pan_id(&mut self, value: Pan)629     pub fn set_dst_pan_id(&mut self, value: Pan) {
630         // NOTE the destination addressing mode must be different than Absent.
631         // This is the reason why we set it to Extended.
632         self.set_dst_addressing_mode(AddressingMode::Extended);
633 
634         let data = self.buffer.as_mut();
635         data[field::ADDRESSING][..2].copy_from_slice(&value.as_bytes());
636     }
637 
638     /// Set the destination address.
639     #[inline]
set_dst_addr(&mut self, value: Address)640     pub fn set_dst_addr(&mut self, value: Address) {
641         match value {
642             Address::Absent => self.set_dst_addressing_mode(AddressingMode::Absent),
643             Address::Short(mut value) => {
644                 value.reverse();
645                 self.set_dst_addressing_mode(AddressingMode::Short);
646                 let data = self.buffer.as_mut();
647                 data[field::ADDRESSING][2..2 + 2].copy_from_slice(&value);
648                 value.reverse();
649             }
650             Address::Extended(mut value) => {
651                 value.reverse();
652                 self.set_dst_addressing_mode(AddressingMode::Extended);
653                 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
654                 data[2..2 + 8].copy_from_slice(&value);
655                 value.reverse();
656             }
657         }
658     }
659 
660     /// Set the destination addressing mode.
661     #[inline]
set_dst_addressing_mode(&mut self, value: AddressingMode)662     fn set_dst_addressing_mode(&mut self, value: AddressingMode) {
663         let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
664         let mut raw = LittleEndian::read_u16(data);
665 
666         raw = (raw & !(0b11 << 10)) | ((u8::from(value) as u16 & 0b11) << 10);
667         data.copy_from_slice(&raw.to_le_bytes());
668     }
669 
670     /// Set the source PAN ID.
671     #[inline]
set_src_pan_id(&mut self, value: Pan)672     pub fn set_src_pan_id(&mut self, value: Pan) {
673         let offset = match self.dst_addressing_mode() {
674             AddressingMode::Absent => 0,
675             AddressingMode::Short => 2,
676             AddressingMode::Extended => 8,
677             _ => unreachable!(),
678         } + 2;
679 
680         let data = &mut self.buffer.as_mut()[field::ADDRESSING];
681         data[offset..offset + 2].copy_from_slice(&value.as_bytes());
682     }
683 
684     /// Set the source address.
685     #[inline]
set_src_addr(&mut self, value: Address)686     pub fn set_src_addr(&mut self, value: Address) {
687         let offset = match self.dst_addressing_mode() {
688             AddressingMode::Absent => 0,
689             AddressingMode::Short => 2,
690             AddressingMode::Extended => 8,
691             _ => unreachable!(),
692         } + 2;
693 
694         let offset = offset + if self.pan_id_compression() { 0 } else { 2 };
695 
696         match value {
697             Address::Absent => self.set_src_addressing_mode(AddressingMode::Absent),
698             Address::Short(mut value) => {
699                 value.reverse();
700                 self.set_src_addressing_mode(AddressingMode::Short);
701                 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
702                 data[offset..offset + 2].copy_from_slice(&value);
703                 value.reverse();
704             }
705             Address::Extended(mut value) => {
706                 value.reverse();
707                 self.set_src_addressing_mode(AddressingMode::Extended);
708                 let data = &mut self.buffer.as_mut()[field::ADDRESSING];
709                 data[offset..offset + 8].copy_from_slice(&value);
710                 value.reverse();
711             }
712         }
713     }
714 
715     /// Set the source addressing mode.
716     #[inline]
set_src_addressing_mode(&mut self, value: AddressingMode)717     fn set_src_addressing_mode(&mut self, value: AddressingMode) {
718         let data = &mut self.buffer.as_mut()[field::FRAMECONTROL];
719         let mut raw = LittleEndian::read_u16(data);
720 
721         raw = (raw & !(0b11 << 14)) | ((u8::from(value) as u16 & 0b11) << 14);
722         data.copy_from_slice(&raw.to_le_bytes());
723     }
724 
725     /// Return a mutable pointer to the payload.
726     #[inline]
payload_mut(&mut self) -> Option<&mut [u8]>727     pub fn payload_mut(&mut self) -> Option<&mut [u8]> {
728         match self.frame_type() {
729             FrameType::Data => {
730                 let index = self.payload_start();
731                 let data = self.buffer.as_mut();
732                 Some(&mut data[index..])
733             }
734             _ => None,
735         }
736     }
737 }
738 
739 impl<T: AsRef<[u8]>> fmt::Display for Frame<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result740     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
741         write!(
742             f,
743             "IEEE802.15.4 frame type={} seq={:2x?} dst_pan={:x?} dest={:x?} src_pan={:?} src={:x?}",
744             self.frame_type(),
745             self.sequence_number(),
746             self.dst_pan_id(),
747             self.dst_addr(),
748             self.src_pan_id(),
749             self.src_addr(),
750         )
751     }
752 }
753 
754 /// A high-level representation of an IEEE802.15.4 frame.
755 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
756 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
757 pub struct Repr {
758     pub frame_type: FrameType,
759     pub security_enabled: bool,
760     pub frame_pending: bool,
761     pub ack_request: bool,
762     pub sequence_number: Option<u8>,
763     pub pan_id_compression: bool,
764     pub frame_version: FrameVersion,
765     pub dst_pan_id: Option<Pan>,
766     pub dst_addr: Option<Address>,
767     pub src_pan_id: Option<Pan>,
768     pub src_addr: Option<Address>,
769 }
770 
771 impl Repr {
772     /// Parse an IEEE 802.15.4 frame and return a high-level representation.
parse<T: AsRef<[u8]> + ?Sized>(packet: &Frame<&T>) -> Result<Repr>773     pub fn parse<T: AsRef<[u8]> + ?Sized>(packet: &Frame<&T>) -> Result<Repr> {
774         // Ensure the basic accessors will work.
775         packet.check_len()?;
776 
777         Ok(Repr {
778             frame_type: packet.frame_type(),
779             security_enabled: packet.security_enabled(),
780             frame_pending: packet.frame_pending(),
781             ack_request: packet.ack_request(),
782             sequence_number: packet.sequence_number(),
783             pan_id_compression: packet.pan_id_compression(),
784             frame_version: packet.frame_version(),
785             dst_pan_id: packet.dst_pan_id(),
786             dst_addr: packet.dst_addr(),
787             src_pan_id: packet.src_pan_id(),
788             src_addr: packet.src_addr(),
789         })
790     }
791 
792     /// Return the length of a buffer required to hold a packet with the payload of a given length.
793     #[inline]
buffer_len(&self) -> usize794     pub const fn buffer_len(&self) -> usize {
795         3 + 2
796             + match self.dst_addr {
797                 Some(Address::Absent) | None => 0,
798                 Some(Address::Short(_)) => 2,
799                 Some(Address::Extended(_)) => 8,
800             }
801             + if !self.pan_id_compression { 2 } else { 0 }
802             + match self.src_addr {
803                 Some(Address::Absent) | None => 0,
804                 Some(Address::Short(_)) => 2,
805                 Some(Address::Extended(_)) => 8,
806             }
807     }
808 
809     /// Emit a high-level representation into an IEEE802.15.4 frame.
emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, frame: &mut Frame<T>)810     pub fn emit<T: AsRef<[u8]> + AsMut<[u8]>>(&self, frame: &mut Frame<T>) {
811         frame.set_frame_type(self.frame_type);
812         frame.set_security_enabled(self.security_enabled);
813         frame.set_frame_pending(self.frame_pending);
814         frame.set_ack_request(self.ack_request);
815         frame.set_pan_id_compression(self.pan_id_compression);
816         frame.set_frame_version(self.frame_version);
817 
818         if let Some(sequence_number) = self.sequence_number {
819             frame.set_sequence_number(sequence_number);
820         }
821 
822         if let Some(dst_pan_id) = self.dst_pan_id {
823             frame.set_dst_pan_id(dst_pan_id);
824         }
825         if let Some(dst_addr) = self.dst_addr {
826             frame.set_dst_addr(dst_addr);
827         }
828 
829         if !self.pan_id_compression && self.src_pan_id.is_some() {
830             frame.set_src_pan_id(self.src_pan_id.unwrap());
831         }
832 
833         if let Some(src_addr) = self.src_addr {
834             frame.set_src_addr(src_addr);
835         }
836     }
837 }
838 
839 #[cfg(test)]
840 mod test {
841     use super::*;
842 
843     #[test]
test_broadcast()844     fn test_broadcast() {
845         assert!(Address::BROADCAST.is_broadcast());
846         assert!(!Address::BROADCAST.is_unicast());
847     }
848 
849     #[test]
prepare_frame()850     fn prepare_frame() {
851         let mut buffer = [0u8; 128];
852 
853         let repr = Repr {
854             frame_type: FrameType::Data,
855             security_enabled: false,
856             frame_pending: false,
857             ack_request: true,
858             pan_id_compression: true,
859             frame_version: FrameVersion::Ieee802154,
860             sequence_number: Some(1),
861             dst_pan_id: Some(Pan(0xabcd)),
862             dst_addr: Some(Address::BROADCAST),
863             src_pan_id: None,
864             src_addr: Some(Address::Extended([
865                 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00,
866             ])),
867         };
868 
869         let buffer_len = repr.buffer_len();
870 
871         let mut frame = Frame::new_unchecked(&mut buffer[..buffer_len]);
872         repr.emit(&mut frame);
873 
874         println!("{frame:2x?}");
875 
876         assert_eq!(frame.frame_type(), FrameType::Data);
877         assert!(!frame.security_enabled());
878         assert!(!frame.frame_pending());
879         assert!(frame.ack_request());
880         assert!(frame.pan_id_compression());
881         assert_eq!(frame.frame_version(), FrameVersion::Ieee802154);
882         assert_eq!(frame.sequence_number(), Some(1));
883         assert_eq!(frame.dst_pan_id(), Some(Pan(0xabcd)));
884         assert_eq!(frame.dst_addr(), Some(Address::BROADCAST));
885         assert_eq!(frame.src_pan_id(), None);
886         assert_eq!(
887             frame.src_addr(),
888             Some(Address::Extended([
889                 0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00
890             ]))
891         );
892     }
893 
894     macro_rules! vector_test {
895         ($name:ident $bytes:expr ; $($test_method:ident -> $expected:expr,)*) => {
896             #[test]
897             #[allow(clippy::bool_assert_comparison)]
898             fn $name() -> Result<()> {
899                 let frame = &$bytes;
900                 let frame = Frame::new_checked(frame)?;
901 
902                 $(
903                     assert_eq!(frame.$test_method(), $expected, stringify!($test_method));
904                 )*
905 
906                 Ok(())
907             }
908         }
909     }
910 
911     vector_test! {
912         extended_addr
913         [
914             0b0000_0001, 0b1100_1100, // frame control
915             0b0, // seq
916             0xcd, 0xab, // pan id
917             0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // dst addr
918             0x03, 0x04, // pan id
919             0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, // src addr
920         ];
921         frame_type -> FrameType::Data,
922         dst_addr -> Some(Address::Extended([0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00])),
923         src_addr -> Some(Address::Extended([0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00])),
924         dst_pan_id -> Some(Pan(0xabcd)),
925     }
926 
927     vector_test! {
928         short_addr
929         [
930             0x01, 0x98,             // frame control
931             0x00,                   // sequence number
932             0x34, 0x12, 0x78, 0x56, // PAN identifier and address of destination
933             0x34, 0x12, 0xbc, 0x9a, // PAN identifier and address of source
934         ];
935         frame_type -> FrameType::Data,
936         security_enabled -> false,
937         frame_pending -> false,
938         ack_request -> false,
939         pan_id_compression -> false,
940         dst_addressing_mode -> AddressingMode::Short,
941         frame_version -> FrameVersion::Ieee802154_2006,
942         src_addressing_mode -> AddressingMode::Short,
943         dst_pan_id -> Some(Pan(0x1234)),
944         dst_addr -> Some(Address::Short([0x56, 0x78])),
945         src_pan_id -> Some(Pan(0x1234)),
946         src_addr -> Some(Address::Short([0x9a, 0xbc])),
947     }
948 
949     vector_test! {
950         zolertia_remote
951         [
952             0x41, 0xd8, // frame control
953             0x01, // sequence number
954             0xcd, 0xab, // Destination PAN id
955             0xff, 0xff, // Short destination address
956             0xc7, 0xd9, 0xb5, 0x14, 0x00, 0x4b, 0x12, 0x00, // Extended source address
957             0x2b, 0x00, 0x00, 0x00, // payload
958         ];
959         frame_type -> FrameType::Data,
960         security_enabled -> false,
961         frame_pending -> false,
962         ack_request -> false,
963         pan_id_compression -> true,
964         dst_addressing_mode -> AddressingMode::Short,
965         frame_version -> FrameVersion::Ieee802154_2006,
966         src_addressing_mode -> AddressingMode::Extended,
967         payload -> Some(&[0x2b, 0x00, 0x00, 0x00][..]),
968     }
969 
970     vector_test! {
971         security
972         [
973             0x69,0xdc, // frame control
974             0x32, // sequence number
975             0xcd,0xab, // destination PAN id
976             0xbf,0x9b,0x15,0x06,0x00,0x4b,0x12,0x00, // extended destination address
977             0xc7,0xd9,0xb5,0x14,0x00,0x4b,0x12,0x00, // extended source address
978             0x05, // security control field
979             0x31,0x01,0x00,0x00, // frame counter
980             0x3e,0xe8,0xfb,0x85,0xe4,0xcc,0xf4,0x48,0x90,0xfe,0x56,0x66,0xf7,0x1c,0x65,0x9e,0xf9, // data
981             0x93,0xc8,0x34,0x2e,// MIC
982         ];
983         frame_type -> FrameType::Data,
984         security_enabled -> true,
985         frame_pending -> false,
986         ack_request -> true,
987         pan_id_compression -> true,
988         dst_addressing_mode -> AddressingMode::Extended,
989         frame_version -> FrameVersion::Ieee802154_2006,
990         src_addressing_mode -> AddressingMode::Extended,
991         dst_pan_id -> Some(Pan(0xabcd)),
992         dst_addr -> Some(Address::Extended([0x00,0x12,0x4b,0x00,0x06,0x15,0x9b,0xbf])),
993         src_pan_id -> None,
994         src_addr -> Some(Address::Extended([0x00,0x12,0x4b,0x00,0x14,0xb5,0xd9,0xc7])),
995         security_level -> 5,
996         key_identifier_mode -> 0,
997         frame_counter -> 305,
998         key_source -> None,
999         key_index -> None,
1000         payload -> Some(&[0x3e,0xe8,0xfb,0x85,0xe4,0xcc,0xf4,0x48,0x90,0xfe,0x56,0x66,0xf7,0x1c,0x65,0x9e,0xf9,0x93,0xc8,0x34,0x2e][..]),
1001         message_integrity_code -> Some(&[0x93, 0xC8, 0x34, 0x2E][..]),
1002         mac_header -> &[
1003             0x69,0xdc, // frame control
1004             0x32, // sequence number
1005             0xcd,0xab, // destination PAN id
1006             0xbf,0x9b,0x15,0x06,0x00,0x4b,0x12,0x00, // extended destination address
1007             0xc7,0xd9,0xb5,0x14,0x00,0x4b,0x12,0x00, // extended source address
1008             0x05, // security control field
1009             0x31,0x01,0x00,0x00, // frame counter
1010         ][..],
1011     }
1012 }
1013