dot15d4_frame/
lib.rs

1//! Zero-copy read and write structures for handling IEEE 802.15.4 MAC frames.
2//!
3//! Each reader contains the following functions:
4//! - [`new`]: Create a new reader.
5//! - [`check_len`]: Check if the buffer is long enough to contain a valid
6//!   frame.
7//! - [`new_unchecked`]: Create a new reader without checking the buffer length.
8//!
9//! The most important reader is the [`Frame`] reader, which is used to read a
10//! full IEEE 802.15.4 frame. The reader provides the following functions:
11//! - [`frame_control`]: returns a [`FrameControl`] reader.
12//! - [`sequence_number`]: returns the sequence number if not suppressed.
13//! - [`addressing`]: returns an [`AddressingFields`] reader.
14//! - [`auxiliary_security_header`]: returns an [`AuxiliarySecurityHeader`]
15//!   reader.
16//! - [`information_elements`]: returns an [`InformationElements`] reader.
17//! - [`payload`]: returns the payload of the frame.
18//!
19//! ## Reading a frame
20//! For an incoming frame, use the [`Frame`] structure to read its content.
21//! ```
22//! # use dot15d4_frame::{
23//! #   Frame,
24//! #   FrameControl,
25//! #   FrameType,
26//! #   AddressingFields,
27//! #   NestedInformationElementsIterator,
28//! #   PayloadGroupId,
29//! #   NestedSubId,
30//! #   NestedSubIdShort,
31//! #   TschTimeslot,
32//! # };
33//! # let frame: [u8; 35] = [
34//! #     0x40, 0xeb, 0xcd, 0xab, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
35//! #     0x00, 0x3f, 0x11, 0x88, 0x06, 0x1a, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c,
36//! #     0x00, 0x01, 0xc8, 0x00, 0x01, 0x1b, 0x00,
37//! # ];
38//! let frame = Frame::new(&frame).unwrap();
39//! let fc = frame.frame_control();
40//! let src_addr = frame.addressing().unwrap().src_address();
41//! let dst_addr = frame.addressing().unwrap().dst_address();
42//!
43//! assert_eq!(fc.frame_type(), FrameType::Beacon);
44//!
45//! let Some(ie) = frame.information_elements() else { return; };
46//!
47//! for payload in ie.payload_information_elements() {
48//!      if matches!(payload.group_id(), PayloadGroupId::Mlme) {
49//!         for nested in payload.nested_information_elements() {
50//!              match nested.sub_id() {
51//!                  NestedSubId::Short(NestedSubIdShort::TschTimeslot) => {
52//!                      let time_slot = TschTimeslot::new(nested.content()).unwrap();
53//!                      assert_eq!(time_slot.id(), 0);
54//!                  }
55//!                  _ => (),
56//!              }
57//!          }
58//!      }
59//!  }
60//! ```
61//!
62//! ## Writing a frame
63//!
64//! __Work in progress!__
65//!
66//! ## Information Elements
67//!
68//! The IEEE 802.15.4 standard defines a set of Information Elements (IEs) that
69//! can be included in the frame. These IEs are used to provide additional
70//! information about the frame, such as timestamping, channel hopping, and
71//! more. The IEs are divided into two groups: Header IEs and Payload IEs.
72//! Calling [`information_elements`] on a [`Frame`] reader returns an
73//! [`InformationElements`] reader. The reader provides access to the Header and
74//! Payload IEs, via the [`header_information_elements`] and
75//! [`payload_information_elements`] functions.
76//!
77//! ### Header Information Elements
78//!
79//! The Header IEs are located in the frame header, and are used to provide
80//! information about the frame itself. The following IEs are defined in the
81//! standard:
82//!
83//! - [x] [`VendorSpecific`]
84//! - [x] [`Csl`]
85//! - [x] [`Rit`]
86//! - [ ] `DsmePanDescriptor`
87//! - [x] [`RendezvousTime`]
88//! - [x] [`TimeCorrection`]
89//! - [ ] `ExtededDsmePanDescriptor`
90//! - [ ] `FragmentSequencecontextDescription`
91//! - [x] [`SimplifiedSuperframeSpecification`]
92//! - [ ] `SimplifiedGtsSpecification`
93//! - [ ] `LecimCapabilities`
94//! - [ ] `TrleDescriptor`
95//! - [ ] `RccCapabilities`
96//! - [ ] `RccnDescriptor`
97//! - [ ] `GlobalTime`
98//! - [ ] `Da`
99//! - [x] [`HeaderTermination1`]
100//! - [x] [`HeaderTermination2`]
101//!
102//! ### Payload Information Elements
103//!
104//! The Payload IEs are located in the frame payload, and are used to provide
105//! information about the payload itself. The following IEs are defined in the
106//! standard:
107//!
108//! - [ ] `Esdu`
109//! - [x] `Mlme`: The MLME group contains a set of nested IEs. Call
110//!   [`nested_information_elements`]
111//!   to get an iterator over the nested IEs.
112//! - [ ] `VendorSpecific`
113//! - [ ] `PayloadTermination`
114//!
115//! ### Nested Information Elements
116//!
117//! Some IEs contain nested IEs. The [`NestedInformationElementsIterator`]
118//! provides an iterator over the nested IEs. The iterator is used to parse the
119//! nested IEs.
120//!
121//! The Nested IEs are split into two groups: Short and Long. The following
122//! short IEs are defined in the standard:
123//!
124//! - [x] [`TschSynchronization`]
125//! - [x] [`TschSlotframeAndLink`]
126//! - [x] [`TschTimeslot`]
127//! - [ ] `HoppingTiming`
128//! - [ ] `EnhancedBeaconFilter`
129//! - [ ] `MacMetrics`
130//! - [ ] `AllMacMetrics`
131//! - [ ] `CoexistenceSpecification`
132//! - [ ] `SunDeviceCapabilities`
133//! - [ ] `SunFskGenericPhy`
134//! - [ ] `ModeSwitchParameter`
135//! - [ ] `PhyParameterChange`
136//! - [ ] `OQpskPhyMode`
137//! - [ ] `PcaAllocation`
138//! - [ ] `LecimDsssOperatingMode`
139//! - [ ] `LecimFskOperatingMode`
140//! - [ ] `TvwsPhyOperatingMode`
141//! - [ ] `TvwsDeviceCapabilities`
142//! - [ ] `TvwsDeviceCategory`
143//! - [ ] `TvwsDeviceIdentification`
144//! - [ ] `TvwsDeviceLocation`
145//! - [ ] `TvwsChannelInformationQuery`
146//! - [ ] `TvwsChannelInformationSource`
147//! - [ ] `Ctm`
148//! - [ ] `Timestamp`
149//! - [ ] `TimestampDifference`
150//! - [ ] `TmctpSpecification`
151//! - [ ] `RccPhyOperatingMode`
152//! - [ ] `LinkMargin`
153//! - [ ] `RsGfskDeviceCapabilities`
154//! - [ ] `MultiPhy`
155//! - [ ] `VendorSpecific`
156//! - [ ] `Srm`
157//!
158//! The following long IEs are defined in the standard:
159//!
160//! - [ ] `VendorSpecificNested`
161//! - [x] [`ChannelHopping`]
162//!
163//! [`new`]: Frame::new
164//! [`check_len`]: Frame::check_len
165//! [`new_unchecked`]: Frame::new_unchecked
166//! [`frame_control`]: Frame::frame_control
167//! [`sequence_number`]: Frame::sequence_number
168//! [`addressing`]: Frame::addressing
169//! [`auxiliary_security_header`]: Frame::auxiliary_security_header
170//! [`information_elements`]: Frame::information_elements
171//! [`payload`]: Frame::payload
172//! [`HeaderTermination1`]: HeaderElementId::HeaderTermination1
173//! [`HeaderTermination2`]: HeaderElementId::HeaderTermination2
174//! [`header_information_elements`]: InformationElements::header_information_elements
175//! [`payload_information_elements`]: InformationElements::payload_information_elements
176//! [`nested_information_elements`]: PayloadInformationElement::nested_information_elements
177
178#![cfg_attr(not(any(test, feature = "std")), no_std)]
179#![deny(missing_docs)]
180#![deny(unsafe_code)]
181
182#[cfg(test)]
183mod tests;
184
185mod time;
186
187mod frame_control;
188pub use frame_control::*;
189
190mod aux_sec_header;
191pub use aux_sec_header::*;
192
193mod addressing;
194pub use addressing::*;
195
196mod ie;
197pub use ie::*;
198
199mod repr;
200pub use repr::*;
201
202/// An error that can occur when reading or writing an IEEE 802.15.4 frame.
203#[derive(Debug, Clone, Copy)]
204pub struct Error;
205
206/// A type alias for `Result<T, frame::Error>`.
207pub type Result<T> = core::result::Result<T, Error>;
208
209/// A reader/writer for an IEEE 802.15.4 frame.
210#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211pub struct Frame<T: AsRef<[u8]>> {
212    buffer: T,
213}
214
215impl<T: AsRef<[u8]>> Frame<T> {
216    /// Create a new [`Frame`] reader/writer from a given buffer.
217    ///
218    /// # Errors
219    ///
220    /// Returns an error if the buffer is too short to contain a valid frame.
221    pub fn new(buffer: T) -> Result<Self> {
222        let b = Self::new_unchecked(buffer);
223
224        if !b.check_len() {
225            return Err(Error);
226        }
227
228        let fc = b.frame_control();
229
230        if fc.security_enabled() {
231            return Err(Error);
232        }
233
234        if fc.frame_type() == FrameType::Unknown {
235            return Err(Error);
236        }
237
238        if fc.frame_version() == FrameVersion::Unknown {
239            return Err(Error);
240        }
241
242        if fc.dst_addressing_mode() == AddressingMode::Unknown {
243            return Err(Error);
244        }
245
246        if fc.src_addressing_mode() == AddressingMode::Unknown {
247            return Err(Error);
248        }
249
250        Ok(b)
251    }
252
253    /// Returns `false` if the buffer is too short to contain a valid frame.
254    fn check_len(&self) -> bool {
255        let buffer = self.buffer.as_ref();
256
257        if buffer.len() < 2 || buffer.len() > 127 {
258            return false;
259        }
260
261        let fc = self.frame_control();
262
263        if !fc.sequence_number_suppression() && buffer.len() < 3 {
264            return false;
265        }
266
267        true
268    }
269
270    /// Create a new [`Frame`] reader/writer from a given buffer without length
271    /// checking.
272    pub fn new_unchecked(buffer: T) -> Self {
273        Self { buffer }
274    }
275
276    /// Return a [`FrameControl`] reader.
277    pub fn frame_control(&self) -> FrameControl<&'_ [u8]> {
278        FrameControl::new_unchecked(&self.buffer.as_ref()[..2])
279    }
280
281    /// Return the sequence number if not suppressed.
282    pub fn sequence_number(&self) -> Option<u8> {
283        if self.frame_control().sequence_number_suppression() {
284            None
285        } else {
286            Some(self.buffer.as_ref()[2])
287        }
288    }
289
290    /// Return an [`AddressingFields`] reader.
291    pub fn addressing(&self) -> Option<AddressingFields<&'_ [u8], &'_ [u8]>> {
292        let fc = self.frame_control();
293
294        if matches!(fc.frame_type(), FrameType::Ack)
295            && matches!(
296                fc.frame_version(),
297                FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006
298            )
299        {
300            // Immediate Acks don't have addressing fields.
301            return None;
302        }
303
304        if fc.sequence_number_suppression() {
305            AddressingFields::new(&self.buffer.as_ref()[2..], fc).ok()
306        } else {
307            AddressingFields::new(&self.buffer.as_ref()[3..], fc).ok()
308        }
309    }
310
311    /// Return an [`AuxiliarySecurityHeader`] reader.
312    pub fn auxiliary_security_header(&self) -> Option<AuxiliarySecurityHeader<&'_ [u8]>> {
313        let fc = self.frame_control();
314
315        if fc.security_enabled() {
316            let mut offset = 2;
317
318            offset += !fc.sequence_number_suppression() as usize;
319
320            if let Some(af) = self.addressing() {
321                offset += af.len();
322            }
323
324            Some(AuxiliarySecurityHeader::new(
325                &self.buffer.as_ref()[offset..],
326            ))
327        } else {
328            None
329        }
330    }
331
332    /// Return an [`InformationElements`] reader.
333    pub fn information_elements(&self) -> Option<InformationElements<&'_ [u8]>> {
334        let fc = self.frame_control();
335        if fc.information_elements_present() {
336            let mut offset = 2;
337            offset += !fc.sequence_number_suppression() as usize;
338
339            if let Some(af) = self.addressing() {
340                offset += af.len();
341            }
342
343            Some(InformationElements::new(&self.buffer.as_ref()[offset..]).ok()?)
344        } else {
345            None
346        }
347    }
348}
349
350impl<'f, T: AsRef<[u8]> + ?Sized> Frame<&'f T> {
351    /// Return the payload of the frame.
352    pub fn payload(&self) -> Option<&'f [u8]> {
353        let fc = self.frame_control();
354
355        let mut offset = 0;
356        offset += 2;
357
358        if !fc.sequence_number_suppression() {
359            offset += 1;
360        }
361
362        if let Some(af) = self.addressing() {
363            offset += af.len();
364        }
365
366        if fc.security_enabled() {
367            offset += self.auxiliary_security_header().unwrap().len();
368        }
369
370        if fc.information_elements_present() {
371            if let Some(ie) = self.information_elements() {
372                offset += ie.len();
373            }
374        }
375
376        if self.buffer.as_ref().len() <= offset {
377            return None;
378        }
379
380        Some(&self.buffer.as_ref()[offset..])
381    }
382}
383
384impl<T: AsRef<[u8]> + AsMut<[u8]>> Frame<T> {
385    /// Set the Frame Control field values in the buffer, based on the given
386    /// [`FrameControlRepr`].
387    pub fn set_frame_control(&mut self, fc: &FrameControlRepr) {
388        let mut w = FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2]);
389        w.set_frame_type(fc.frame_type);
390        w.set_security_enabled(fc.security_enabled);
391        w.set_frame_pending(fc.frame_pending);
392        w.set_ack_request(fc.ack_request);
393        w.set_pan_id_compression(fc.pan_id_compression);
394        w.set_sequence_number_suppression(fc.sequence_number_suppression);
395        w.set_information_elements_present(fc.information_elements_present);
396        w.set_dst_addressing_mode(fc.dst_addressing_mode);
397        w.set_src_addressing_mode(fc.src_addressing_mode);
398        w.set_frame_version(fc.frame_version);
399    }
400
401    /// Get a mutable reference to the Frame Control fields
402    pub fn frame_control_mut(&mut self) -> FrameControl<&'_ mut [u8]> {
403        FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2])
404    }
405
406    /// Set the Sequence Number field value in the buffer.
407    pub fn set_sequence_number(&mut self, sequence_number: u8) {
408        // Set the sequence number suppression bit to false.
409        let mut w = FrameControl::new_unchecked(&mut self.buffer.as_mut()[..2]);
410        w.set_sequence_number_suppression(false);
411
412        self.buffer.as_mut()[2] = sequence_number;
413    }
414
415    /// Set the Addressing field values in the buffer, based on the given
416    /// [`AddressingFieldsRepr`].
417    pub fn set_addressing_fields(&mut self, addressing_fields: &AddressingFieldsRepr) {
418        let start = 2 + (!self.frame_control().sequence_number_suppression() as usize);
419
420        let (fc, addressing) = self.buffer.as_mut().split_at_mut(start);
421        let mut w = AddressingFields::new_unchecked(addressing, FrameControl::new_unchecked(fc));
422        w.write_fields(addressing_fields);
423    }
424
425    /// Set the Auxiliary Security Header field values in the buffer, based on
426    /// the given _.
427    pub fn set_aux_sec_header(&mut self) {
428        todo!();
429    }
430
431    /// Set the Information Elements field values in the buffer, based on the
432    /// given _.
433    pub fn set_information_elements(
434        &mut self,
435        ie: &InformationElementsRepr,
436        contains_payload: bool,
437    ) {
438        let mut offset = 2;
439        offset += !self.frame_control().sequence_number_suppression() as usize;
440
441        if let Some(af) = self.addressing() {
442            offset += af.len();
443        }
444
445        ie.emit(&mut self.buffer.as_mut()[offset..], contains_payload);
446    }
447
448    /// Set the payload of the frame.
449    pub fn set_payload(&mut self, payload: &[u8]) {
450        let mut offset = 0;
451        offset += 2;
452
453        if !self.frame_control().sequence_number_suppression() {
454            offset += 1;
455        }
456
457        if let Some(af) = self.addressing() {
458            offset += af.len();
459        }
460
461        if self.frame_control().security_enabled() {
462            offset += self.auxiliary_security_header().unwrap().len();
463        }
464
465        if self.frame_control().information_elements_present() {
466            offset += self.information_elements().unwrap().len();
467        }
468
469        self.buffer.as_mut()[offset..].copy_from_slice(payload);
470    }
471}
472
473impl<'f, T: AsRef<[u8]> + ?Sized> core::fmt::Display for Frame<&'f T> {
474    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
475        let fc = self.frame_control();
476        write!(f, "{}", fc)?;
477        if !fc.sequence_number_suppression() {
478            writeln!(f, "Sequence number: {}", self.sequence_number().unwrap())?;
479        }
480
481        if let Some(af) = self.addressing() {
482            write!(f, "{af}")?;
483        }
484
485        if fc.security_enabled() {
486            todo!();
487        }
488
489        if let Some(ie) = self.information_elements() {
490            writeln!(f, "Information Elements")?;
491            for header_ie in ie.header_information_elements() {
492                writeln!(f, "  {}", header_ie)?;
493            }
494
495            for payload_ie in ie.payload_information_elements() {
496                writeln!(f, "  {}", payload_ie)?;
497            }
498        }
499
500        if let Some(payload) = self.payload() {
501            writeln!(f, "Payload")?;
502            writeln!(f, "  {:0x?}", payload)?;
503        }
504
505        Ok(())
506    }
507}