capsules_extra/net/
ieee802154.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implements IEEE 802.15.4-2015 header encoding and decoding.
6//! Supports the general MAC frame format, which encompasses data frames, beacon
7//! frames, MAC command frames, and the like.
8
9use crate::net::stream::SResult;
10use crate::net::stream::{decode_bytes_be, decode_u16, decode_u32, decode_u8};
11use crate::net::stream::{encode_bytes, encode_bytes_be, encode_u16, encode_u32, encode_u8};
12
13#[derive(Copy, Clone, Eq, PartialEq, Debug)]
14pub enum MacAddress {
15    Short(u16),
16    Long([u8; 8]),
17}
18
19impl MacAddress {
20    pub fn encode(&self, buf: &mut [u8]) -> SResult {
21        match *self {
22            MacAddress::Short(ref short_addr) => encode_u16(buf, short_addr.to_be()),
23            MacAddress::Long(ref long_addr) => encode_bytes_be(buf, long_addr),
24        }
25    }
26
27    pub fn decode(buf: &[u8], mode: AddressMode) -> SResult<Option<MacAddress>> {
28        match mode {
29            AddressMode::NotPresent => stream_done!(0, None),
30            AddressMode::Short => {
31                let (off, short_addr_be) = dec_try!(buf; decode_u16);
32                let short_addr = u16::from_be(short_addr_be);
33                stream_done!(off, Some(MacAddress::Short(short_addr)));
34            }
35            AddressMode::Long => {
36                let mut long_addr = [0u8; 8];
37                let off = dec_consume!(buf; decode_bytes_be, &mut long_addr);
38                stream_done!(off, Some(MacAddress::Long(long_addr)));
39            }
40        }
41    }
42}
43
44pub type PanID = u16;
45
46mod frame_control {
47    pub const FRAME_TYPE_MASK: u16 = 0b111;
48    pub const SECURITY_ENABLED: u16 = 1 << 3;
49    pub const FRAME_PENDING: u16 = 1 << 4;
50    pub const ACK_REQUESTED: u16 = 1 << 5;
51    pub const PAN_ID_COMPRESSION: u16 = 1 << 6;
52    pub const SEQ_SUPPRESSED: u16 = 1 << 8;
53    pub const IE_PRESENT: u16 = 1 << 9;
54    pub const DST_MODE_POS: usize = 10;
55    pub const FRAME_VERSION_MASK: u16 = 0b11 << 12;
56    pub const SRC_MODE_POS: usize = 14;
57    pub const MODE_MASK: u16 = 0b11;
58}
59
60#[repr(u16)]
61#[derive(Copy, Clone, Eq, PartialEq, Debug)]
62pub enum FrameType {
63    // Reserved = 0b100,
64    Beacon = 0b000,
65    Data = 0b001,
66    Acknowledgement = 0b010,
67    MACCommand = 0b011,
68    Multipurpose = 0b101,
69    Fragment = 0b110,
70    Extended = 0b111,
71}
72
73impl FrameType {
74    pub fn from_fcf(fcf: u16) -> Option<FrameType> {
75        match fcf & frame_control::FRAME_TYPE_MASK {
76            0b000 => Some(FrameType::Beacon),
77            0b001 => Some(FrameType::Data),
78            0b010 => Some(FrameType::Acknowledgement),
79            0b011 => Some(FrameType::MACCommand),
80            0b101 => Some(FrameType::Multipurpose),
81            0b110 => Some(FrameType::Fragment),
82            0b111 => Some(FrameType::Extended),
83            _ => None,
84        }
85    }
86}
87
88#[repr(u16)]
89#[derive(Copy, Clone, Eq, PartialEq, Debug)]
90pub enum FrameVersion {
91    // Reserved = 0x3000
92    V2003 = 0x0000,
93    V2006 = 0x1000,
94    V2015 = 0x2000,
95}
96
97impl FrameVersion {
98    pub fn from_fcf(fcf: u16) -> Option<FrameVersion> {
99        match fcf & frame_control::FRAME_VERSION_MASK {
100            0x0000 => Some(FrameVersion::V2003),
101            0x1000 => Some(FrameVersion::V2006),
102            0x2000 => Some(FrameVersion::V2015),
103            _ => None,
104        }
105    }
106}
107
108#[repr(u8)]
109#[derive(Copy, Clone, Eq, PartialEq, Debug)]
110pub enum AddressMode {
111    NotPresent = 0b00,
112    Short = 0b10,
113    Long = 0b11,
114}
115
116impl<'a> From<&'a Option<MacAddress>> for AddressMode {
117    fn from(opt_addr: &'a Option<MacAddress>) -> Self {
118        match *opt_addr {
119            None => AddressMode::NotPresent,
120            Some(addr) => match addr {
121                MacAddress::Short(_) => AddressMode::Short,
122                MacAddress::Long(_) => AddressMode::Long,
123            },
124        }
125    }
126}
127
128impl AddressMode {
129    pub fn from_mode(mode: u16) -> Option<AddressMode> {
130        match mode {
131            0b00 => Some(AddressMode::NotPresent),
132            0b10 => Some(AddressMode::Short),
133            0b11 => Some(AddressMode::Long),
134            _ => None,
135        }
136    }
137}
138
139mod security_control {
140    pub const SECURITY_LEVEL_MASK: u8 = 0b111;
141    pub const KEY_ID_MODE_MASK: u8 = 0b11 << 3;
142    pub const FRAME_COUNTER_SUPPRESSION: u8 = 1 << 5;
143    pub const ASN_IN_NONCE: u8 = 1 << 6;
144}
145
146#[repr(u8)]
147#[derive(Copy, Clone, Eq, PartialEq, Debug)]
148pub enum SecurityLevel {
149    // Reserved = 0b100,
150    None = 0b000,
151    Mic32 = 0b001,
152    Mic64 = 0b010,
153    Mic128 = 0b011,
154    EncMic32 = 0b101,
155    EncMic64 = 0b110,
156    EncMic128 = 0b111,
157}
158
159impl SecurityLevel {
160    pub fn from_scf(scf: u8) -> Option<SecurityLevel> {
161        match scf & security_control::SECURITY_LEVEL_MASK {
162            0b000 => Some(SecurityLevel::None),
163            0b001 => Some(SecurityLevel::Mic32),
164            0b010 => Some(SecurityLevel::Mic64),
165            0b011 => Some(SecurityLevel::Mic128),
166            0b101 => Some(SecurityLevel::EncMic32),
167            0b110 => Some(SecurityLevel::EncMic64),
168            0b111 => Some(SecurityLevel::EncMic128),
169            _ => None,
170        }
171    }
172
173    pub fn encryption_needed(&self) -> bool {
174        match *self {
175            SecurityLevel::EncMic32 | SecurityLevel::EncMic64 | SecurityLevel::EncMic128 => true,
176            _ => false,
177        }
178    }
179
180    pub fn mic_len(&self) -> usize {
181        match *self {
182            SecurityLevel::Mic32 | SecurityLevel::EncMic32 => 4,
183            SecurityLevel::Mic64 | SecurityLevel::EncMic64 => 8,
184            SecurityLevel::Mic128 | SecurityLevel::EncMic128 => 16,
185            _ => 0,
186        }
187    }
188}
189
190#[repr(u8)]
191#[derive(Copy, Clone, Eq, PartialEq, Debug)]
192pub enum KeyIdMode {
193    Implicit = 0x00,
194    Index = 0x08,
195    Source4Index = 0x10,
196    Source8Index = 0x18,
197}
198
199impl KeyIdMode {
200    pub fn from_scf(scf: u8) -> Option<KeyIdMode> {
201        match scf & security_control::KEY_ID_MODE_MASK {
202            0x00 => Some(KeyIdMode::Implicit),
203            0x08 => Some(KeyIdMode::Index),
204            0x10 => Some(KeyIdMode::Source4Index),
205            0x18 => Some(KeyIdMode::Source8Index),
206            _ => panic!("Unreachable case because of mask"),
207        }
208    }
209}
210
211#[derive(Copy, Clone, Eq, PartialEq, Debug)]
212pub enum KeyId {
213    Implicit,
214    Index(u8),
215    Source4Index([u8; 4], u8),
216    Source8Index([u8; 8], u8),
217}
218
219impl KeyId {
220    pub fn encode(&self, buf: &mut [u8]) -> SResult {
221        let off = match *self {
222            KeyId::Implicit => 0,
223            KeyId::Index(index) => enc_consume!(buf; encode_u8, index),
224            KeyId::Source4Index(ref src, index) => {
225                let off = enc_consume!(buf; encode_bytes_be, src);
226                enc_consume!(buf, off; encode_u8, index)
227            }
228            KeyId::Source8Index(ref src, index) => {
229                let off = enc_consume!(buf; encode_bytes_be, src);
230                enc_consume!(buf, off; encode_u8, index)
231            }
232        };
233        stream_done!(off);
234    }
235
236    pub fn decode(buf: &[u8], mode: KeyIdMode) -> SResult<KeyId> {
237        match mode {
238            KeyIdMode::Implicit => stream_done!(0, KeyId::Implicit),
239            KeyIdMode::Index => {
240                let (off, index) = dec_try!(buf; decode_u8);
241                stream_done!(off, KeyId::Index(index));
242            }
243            KeyIdMode::Source4Index => {
244                let mut src = [0u8; 4];
245                let off = dec_consume!(buf; decode_bytes_be, &mut src);
246                let (off, index) = dec_try!(buf, off; decode_u8);
247                stream_done!(off, KeyId::Source4Index(src, index));
248            }
249            KeyIdMode::Source8Index => {
250                let mut src = [0u8; 8];
251                let off = dec_consume!(buf; decode_bytes_be, &mut src);
252                let (off, index) = dec_try!(buf, off; decode_u8);
253                stream_done!(off, KeyId::Source8Index(src, index));
254            }
255        }
256    }
257}
258
259impl<'a> From<&'a KeyId> for KeyIdMode {
260    fn from(key_id: &'a KeyId) -> Self {
261        match *key_id {
262            KeyId::Implicit => KeyIdMode::Implicit,
263            KeyId::Index(_) => KeyIdMode::Index,
264            KeyId::Source4Index(_, _) => KeyIdMode::Source4Index,
265            KeyId::Source8Index(_, _) => KeyIdMode::Source8Index,
266        }
267    }
268}
269
270#[derive(Copy, Clone, Eq, PartialEq, Debug)]
271pub struct Security {
272    pub level: SecurityLevel,
273    pub asn_in_nonce: bool,
274    pub frame_counter: Option<u32>,
275    pub key_id: KeyId,
276}
277
278impl Security {
279    pub fn encode(&self, buf: &mut [u8]) -> SResult {
280        // The security control field is collected while encoding the other
281        // fields in the auxiliary security header, and only written in the end
282        stream_len_cond!(buf, 1);
283        let mut off = 1;
284
285        // Security control field
286        let mut scf = self.level as u8;
287        if self.asn_in_nonce {
288            scf |= security_control::ASN_IN_NONCE;
289        }
290
291        // Frame counter field
292        if let Some(ref frame_counter) = self.frame_counter {
293            off = enc_consume!(buf, off; encode_u32, frame_counter.to_be());
294        } else {
295            scf |= security_control::FRAME_COUNTER_SUPPRESSION;
296        }
297
298        // Key identifier field
299        scf |= KeyIdMode::from(&self.key_id) as u8;
300        off = enc_consume!(buf, off; self.key_id; encode);
301
302        // Put the security control field in front
303        enc_try!(buf; encode_u8, scf);
304        stream_done!(off);
305    }
306
307    pub fn decode(buf: &[u8]) -> SResult<Security> {
308        // Security control field
309        let (off, scf) = dec_try!(buf; decode_u8);
310        let level = stream_from_option!(SecurityLevel::from_scf(scf));
311        let asn_in_nonce = (scf & security_control::ASN_IN_NONCE) != 0;
312
313        // Frame counter field
314        // if frame counter suppresion is enabled, the frame counter field will not be in the header
315        let frame_counter_present = (scf & security_control::FRAME_COUNTER_SUPPRESSION) == 0;
316        let (off, frame_counter) = if frame_counter_present {
317            let (off, frame_counter_be) = dec_try!(buf, off; decode_u32);
318            (off, Some(u32::from_be(frame_counter_be)))
319        } else {
320            (off, None)
321        };
322
323        // Key identifier field
324        let key_id_mode = stream_from_option!(KeyIdMode::from_scf(scf));
325        let (off, key_id) = dec_try!(buf, off; KeyId::decode, key_id_mode);
326
327        stream_done!(
328            off,
329            Security {
330                level,
331                asn_in_nonce,
332                frame_counter,
333                key_id,
334            }
335        );
336    }
337}
338
339mod ie_control {
340    // Header IE constants
341    pub const HEADER_LEN_MAX: usize = (1 << 7) - 1;
342    pub const HEADER_LEN_MASK: u16 = HEADER_LEN_MAX as u16;
343    pub const HEADER_ID_POS: usize = 7;
344
345    // Payload IE constants
346    pub const PAYLOAD_LEN_MAX: usize = (1 << 11) - 1;
347    pub const PAYLOAD_LEN_MASK: u16 = PAYLOAD_LEN_MAX as u16;
348    pub const PAYLOAD_ID_MASK: u8 = 0xf; // Only 4 bits
349    pub const PAYLOAD_ID_POS: usize = 11;
350
351    pub const TYPE: u16 = 0x8000;
352}
353
354#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
355pub enum HeaderIE<'a> {
356    Undissected {
357        element_id: u8,
358        content: &'a [u8],
359    },
360    #[default]
361    Termination1,
362    Termination2,
363}
364
365impl HeaderIE<'_> {
366    pub fn is_termination(&self) -> bool {
367        match *self {
368            HeaderIE::Termination1 | HeaderIE::Termination2 => true,
369            _ => false,
370        }
371    }
372
373    pub fn encode(&self, buf: &mut [u8]) -> SResult {
374        // Append the content field of the IE first
375        let mut off = 2;
376        let element_id: u8 = match *self {
377            HeaderIE::Undissected {
378                element_id,
379                content,
380            } => {
381                off = enc_consume!(buf, off; encode_bytes, content);
382                element_id
383            }
384            HeaderIE::Termination1 => 0x7e,
385            HeaderIE::Termination2 => 0x7f,
386        };
387
388        // Write the two octets that begin each header IE
389        let content_len = off - 2;
390        stream_cond!(content_len <= ie_control::HEADER_LEN_MAX);
391        let ie_ctl = ((content_len as u16) & ie_control::HEADER_LEN_MASK)
392            | ((element_id as u16) << ie_control::HEADER_ID_POS);
393        enc_consume!(buf; encode_u16, ie_ctl.to_be());
394
395        stream_done!(off);
396    }
397
398    pub fn decode(buf: &[u8]) -> SResult<HeaderIE<'_>> {
399        let (off, ie_ctl_be) = dec_try!(buf; decode_u16);
400        let ie_ctl = u16::from_be(ie_ctl_be);
401
402        // Header IEs are type 0
403        stream_cond!(ie_ctl & ie_control::TYPE == 0);
404        let content_len = (ie_ctl & ie_control::HEADER_LEN_MASK) as usize;
405        let element_id = (ie_ctl >> ie_control::HEADER_ID_POS) as u8;
406
407        stream_len_cond!(buf, off + content_len);
408        let content = &buf[off..off + content_len];
409
410        let ie = match element_id {
411            0x7e => HeaderIE::Termination1,
412            0x7f => HeaderIE::Termination2,
413            element_id => HeaderIE::Undissected {
414                element_id,
415                content,
416            },
417        };
418
419        stream_done!(off + content_len, ie);
420    }
421}
422
423#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
424pub enum PayloadIE<'a> {
425    Undissected {
426        group_id: u8,
427        content: &'a [u8],
428    },
429    #[default]
430    Termination,
431}
432
433impl PayloadIE<'_> {
434    pub fn is_termination(&self) -> bool {
435        match *self {
436            PayloadIE::Termination => true,
437            _ => false,
438        }
439    }
440
441    pub fn encode(&self, buf: &mut [u8]) -> SResult {
442        // Append the content field of the IE first
443        let mut off = 2;
444        let group_id: u8 = match *self {
445            PayloadIE::Undissected { group_id, content } => {
446                off = enc_consume!(buf, off; encode_bytes, content);
447                group_id
448            }
449            PayloadIE::Termination => 0xf,
450        };
451
452        // Write the two octets that begin each payload IE
453        let content_len = off - 2;
454        stream_cond!(content_len <= ie_control::PAYLOAD_LEN_MAX);
455        let ie_ctl = ((content_len as u16) & ie_control::PAYLOAD_LEN_MASK)
456            | ((group_id & ie_control::PAYLOAD_ID_MASK) as u16) << ie_control::PAYLOAD_ID_POS;
457        enc_consume!(buf; encode_u16, ie_ctl.to_be());
458
459        stream_done!(off);
460    }
461
462    pub fn decode(buf: &[u8]) -> SResult<PayloadIE<'_>> {
463        let (off, ie_ctl_be) = dec_try!(buf; decode_u16);
464        let ie_ctl = u16::from_be(ie_ctl_be);
465
466        // Payload IEs are type 1
467        stream_cond!(ie_ctl & ie_control::TYPE != 0);
468        let content_len = (ie_ctl & ie_control::PAYLOAD_LEN_MASK) as usize;
469        let element_id =
470            ((ie_ctl >> ie_control::PAYLOAD_ID_POS) as u8) & ie_control::PAYLOAD_ID_MASK;
471
472        stream_len_cond!(buf, off + content_len);
473        let content = &buf[off..off + content_len];
474
475        let ie = match element_id {
476            0xf => PayloadIE::Termination,
477            group_id => PayloadIE::Undissected { group_id, content },
478        };
479
480        stream_done!(off + content_len, ie);
481    }
482}
483
484pub const MAX_HEADER_IES: usize = 5;
485pub const MAX_PAYLOAD_IES: usize = 5;
486
487#[derive(Copy, Clone, Eq, PartialEq, Debug)]
488pub struct Header<'a> {
489    pub frame_type: FrameType,
490    pub frame_pending: bool,
491    pub ack_requested: bool,
492    pub version: FrameVersion,
493    pub seq: Option<u8>,
494    pub dst_pan: Option<PanID>,
495    pub dst_addr: Option<MacAddress>,
496    pub src_pan: Option<PanID>,
497    pub src_addr: Option<MacAddress>,
498    pub security: Option<Security>,
499    pub header_ies: [HeaderIE<'a>; MAX_HEADER_IES],
500    pub header_ies_len: usize,
501    pub payload_ies: [PayloadIE<'a>; MAX_PAYLOAD_IES],
502    pub payload_ies_len: usize,
503}
504
505impl Header<'_> {
506    pub fn encode(&self, buf: &mut [u8], has_payload: bool) -> SResult<usize> {
507        // The frame control field is collected in the course of encoding the
508        // various other fields of the header and then written only at the end
509        stream_len_cond!(buf, 2);
510        let mut off = 2;
511
512        // Sequence number
513        if self.version != FrameVersion::V2015 {
514            // The sequence number is always present before version 2015
515            stream_cond!(self.seq.is_some());
516        }
517        let seq_suppressed = if let Some(seq) = self.seq {
518            off = enc_consume!(buf, off; encode_u8, seq);
519            false
520        } else {
521            true
522        };
523
524        // Addressing fields
525        let (off, pan_id_compression) = enc_try!(buf, off; self; encode_addressing);
526        let dst_mode = AddressMode::from(&self.dst_addr);
527        let src_mode = AddressMode::from(&self.src_addr);
528
529        // Auxiliary security header
530        // Note: security can be enabled with security level 0 (None)
531        let (mut off, security_enabled) = match self.security {
532            None => (off, false),
533            Some(ref security) => (enc_consume!(buf, off; security; encode), true),
534        };
535
536        // Information elements
537        // IE list termination is implicit and handled by encoding/decoding
538        // procedures. Hence, we ensure that there are no termination headers
539        // in our lists.
540        let has_header_ies = self.header_ies_len != 0;
541        let has_payload_ies = self.payload_ies_len != 0;
542        stream_cond!(self.header_ies_len <= MAX_HEADER_IES);
543        stream_cond!(self.payload_ies_len <= MAX_PAYLOAD_IES);
544        for ie in self.header_ies[..self.header_ies_len].iter() {
545            stream_cond!(!ie.is_termination());
546            off = enc_consume!(buf, off; ie; encode);
547        }
548        if has_payload_ies {
549            // terminate with header termination 1
550            off = enc_consume!(buf, off; HeaderIE::Termination1; encode);
551        } else if has_header_ies && has_payload {
552            // terminate with header termination 2
553            off = enc_consume!(buf, off; HeaderIE::Termination2; encode);
554        }
555        // The MAC payload includes payload IEs
556        let mac_payload_off = off;
557        for ie in self.payload_ies[..self.payload_ies_len].iter() {
558            stream_cond!(!ie.is_termination());
559            off = enc_consume!(buf, off; ie; encode);
560        }
561        if has_payload_ies && has_payload {
562            // terminate with payload termination
563            off = enc_consume!(buf, off; PayloadIE::Termination; encode);
564        }
565        let ie_present = has_header_ies || has_payload_ies;
566
567        // Flags that can be independently determined
568        let mut fcf = self.frame_type as u16;
569        if security_enabled {
570            fcf |= frame_control::SECURITY_ENABLED;
571        }
572        if self.frame_pending {
573            fcf |= frame_control::FRAME_PENDING;
574        }
575        if self.ack_requested {
576            fcf |= frame_control::ACK_REQUESTED;
577        }
578        if pan_id_compression {
579            fcf |= frame_control::PAN_ID_COMPRESSION;
580        }
581        if seq_suppressed {
582            fcf |= frame_control::SEQ_SUPPRESSED;
583        }
584        if ie_present {
585            fcf |= frame_control::IE_PRESENT;
586        }
587        fcf |= (dst_mode as u16) << frame_control::DST_MODE_POS;
588        fcf |= self.version as u16;
589        fcf |= (src_mode as u16) << frame_control::SRC_MODE_POS;
590
591        // Put the frame control field in front
592        enc_try!(buf; encode_u16, fcf.to_be());
593        stream_done!(off, mac_payload_off);
594    }
595
596    pub fn encode_addressing(&self, buf: &mut [u8]) -> SResult<bool> {
597        // IEEE 802.15.4: Section 7.2.1.5
598        // The pan ID compression field's meaning is dependent on the version
599        let mut drop_src_pan = false;
600        let pan_id_compression = match self.version {
601            FrameVersion::V2015 => {
602                // In this mode, the only valid combinations are determined by
603                // Table 7-2
604                match (self.dst_addr, self.src_addr) {
605                    (None, None) => {
606                        stream_cond!(self.src_pan.is_none());
607                        self.dst_pan.is_some()
608                    }
609                    (Some(_), None) => {
610                        stream_cond!(self.src_pan.is_none());
611                        self.dst_pan.is_none()
612                    }
613                    (None, Some(_)) => {
614                        stream_cond!(self.dst_pan.is_none());
615                        self.src_pan.is_none()
616                    }
617                    (Some(_), Some(_)) => {
618                        // When both addresses are present, we require that both
619                        // pans are provided, and we will only drop the source
620                        // pan ID if it matches the destination.
621                        drop_src_pan = match (self.dst_pan, self.src_pan) {
622                            (Some(dst_pan), Some(src_pan)) => dst_pan == src_pan,
623                            _ => stream_err!(),
624                        };
625                        drop_src_pan
626                    }
627                }
628            }
629            FrameVersion::V2003 | FrameVersion::V2006 => {
630                // In these two modes, the source pan ID is only omitted if it
631                // matches the destination pan ID. Hence, the user must always
632                // provide a pan ID iff an address is provided.
633                stream_cond!(self.dst_addr.is_some() == self.dst_pan.is_some());
634                stream_cond!(self.src_addr.is_some() == self.src_pan.is_some());
635
636                match (self.dst_pan, self.src_pan) {
637                    (Some(dst_pan), Some(src_pan)) => {
638                        drop_src_pan = dst_pan == src_pan;
639                    }
640                    _ => {}
641                }
642                drop_src_pan
643            }
644        };
645
646        // The presence of the actual address fields are now the same
647        let mut off = 0;
648        if let Some(pan) = self.dst_pan {
649            off = enc_consume!(buf, off; encode_u16, pan.to_be());
650        }
651        if let Some(addr) = self.dst_addr {
652            off = enc_consume!(buf, off; addr; encode);
653        }
654        if let Some(pan) = self.src_pan {
655            if !drop_src_pan {
656                off = enc_consume!(buf, off; encode_u16, pan.to_be());
657            }
658        }
659        if let Some(addr) = self.src_addr {
660            off = enc_consume!(buf, off; addr; encode);
661        }
662
663        stream_done!(off, pan_id_compression);
664    }
665
666    /// Decodes an IEEE 802.15.4 MAC header from a byte slice, where the MAC
667    /// header may contain slices into the given byte slice to represent
668    /// undissected information elements (IE). `unsecured` controls whether or
669    /// not payload IEs (which are encrypted if the frame has not yet been
670    /// unsecured) can be parsed.
671    pub fn decode<'b>(buf: &'b [u8], unsecured: bool) -> SResult<(Header<'b>, usize)> {
672        // Frame control field
673        let (off, fcf_be) = dec_try!(buf; decode_u16);
674        let fcf = u16::from_be(fcf_be);
675
676        // In order of least significant bits first
677        let frame_type = stream_from_option!(FrameType::from_fcf(fcf));
678        let security_enabled = (fcf & frame_control::SECURITY_ENABLED) != 0;
679        let frame_pending = (fcf & frame_control::FRAME_PENDING) != 0;
680        let ack_requested = (fcf & frame_control::ACK_REQUESTED) != 0;
681        let pan_id_compression = (fcf & frame_control::PAN_ID_COMPRESSION) != 0;
682        let seq_suppressed = (fcf & frame_control::SEQ_SUPPRESSED) != 0;
683        let ie_present = (fcf & frame_control::IE_PRESENT) != 0;
684        let dst_mode = {
685            let mode = (fcf >> frame_control::DST_MODE_POS) & frame_control::MODE_MASK;
686            stream_from_option!(AddressMode::from_mode(mode))
687        };
688        let version = stream_from_option!(FrameVersion::from_fcf(fcf));
689        let src_mode = {
690            let mode = (fcf >> frame_control::SRC_MODE_POS) & frame_control::MODE_MASK;
691            stream_from_option!(AddressMode::from_mode(mode))
692        };
693
694        // Sequence number
695        let (off, seq) = if !seq_suppressed {
696            let (off, seq) = dec_try!(buf, off; decode_u8);
697            (off, Some(seq))
698        } else {
699            (off, None)
700        };
701
702        // Addressing fields
703        let (off, (dst_pan, dst_addr, src_pan, src_addr)) = dec_try!(buf, off;
704                                                                     Self::decode_addressing,
705                                                                     version,
706                                                                     dst_mode,
707                                                                     src_mode,
708                                                                     pan_id_compression);
709
710        // Auxiliary security header
711        let (mut off, security) = if security_enabled {
712            let (off, security) = dec_try!(buf, off; Security::decode);
713            (off, Some(security))
714        } else {
715            (off, None)
716        };
717
718        // Information elements
719        let mut header_ies: [HeaderIE<'b>; MAX_HEADER_IES] = Default::default();
720        let mut header_ies_len = 0;
721        let mut payload_ies: [PayloadIE<'b>; MAX_PAYLOAD_IES] = Default::default();
722        let mut payload_ies_len = 0;
723
724        let mut has_payload_ies = false;
725        if ie_present {
726            loop {
727                let (next_off, ie) = dec_try!(buf, off; HeaderIE::decode);
728                off = next_off;
729                match ie {
730                    HeaderIE::Termination1 => {
731                        has_payload_ies = true;
732                        break;
733                    }
734                    HeaderIE::Termination2 => {
735                        break;
736                    }
737                    other_ie => {
738                        stream_cond!(header_ies_len + 1 < MAX_HEADER_IES);
739                        header_ies[header_ies_len] = other_ie;
740                        header_ies_len += 1;
741                    }
742                }
743            }
744        }
745        // The MAC payload includes the payload IEs. We can only parse them if
746        // the frame is not encrypted.
747        let mac_payload_off = off;
748        let unencrypted = unsecured || !security_enabled;
749        if has_payload_ies && unencrypted {
750            loop {
751                let (next_off, ie) = dec_try!(buf, off; PayloadIE::decode);
752                off = next_off;
753                match ie {
754                    PayloadIE::Termination => {
755                        break;
756                    }
757                    other_ie => {
758                        stream_cond!(payload_ies_len + 1 < MAX_PAYLOAD_IES);
759                        payload_ies[payload_ies_len] = other_ie;
760                        payload_ies_len += 1;
761                    }
762                }
763            }
764        }
765
766        stream_done!(
767            off,
768            (
769                Header {
770                    frame_type,
771                    frame_pending,
772                    ack_requested,
773                    version,
774                    seq,
775                    dst_pan,
776                    dst_addr,
777                    src_pan,
778                    src_addr,
779                    security,
780                    header_ies,
781                    header_ies_len,
782                    payload_ies,
783                    payload_ies_len,
784                },
785                mac_payload_off
786            )
787        );
788    }
789
790    pub fn decode_addressing(
791        buf: &[u8],
792        version: FrameVersion,
793        dst_mode: AddressMode,
794        src_mode: AddressMode,
795        pan_id_compression: bool,
796    ) -> SResult<(
797        Option<PanID>,
798        Option<MacAddress>,
799        Option<PanID>,
800        Option<MacAddress>,
801    )> {
802        // IEEE 802.15.4: Section 7.2.1.5
803        // Whether or not the addresses are included is determined by the mode
804        // fields in the frame control field, but the presence of pan IDs
805        // depends on the pan ID compression field and the frame version
806        let mut src_pan_dropped = false;
807        let dst_present = dst_mode != AddressMode::NotPresent;
808        let src_present = src_mode != AddressMode::NotPresent;
809        let (dst_pan_present, src_pan_present) = match version {
810            FrameVersion::V2015 => {
811                // Everything is determined by Table 7-2 in the spec
812                match (dst_present, src_present) {
813                    (false, false) => (pan_id_compression, false),
814                    (true, false) => (!pan_id_compression, false),
815                    (false, true) => (false, !pan_id_compression),
816                    (true, true) => {
817                        src_pan_dropped = pan_id_compression;
818                        (true, !pan_id_compression)
819                    }
820                }
821            }
822            FrameVersion::V2003 | FrameVersion::V2006 => {
823                // In these two modes, pan IDs are specified if addresses are
824                // specified, except when the source pan matches the destination
825                // pan, in which case the source pan is omitted and the pan ID
826                // compression flag is set
827                src_pan_dropped = pan_id_compression;
828                (dst_present, src_present && !src_pan_dropped)
829            }
830        };
831
832        let off = 0;
833        let (off, dst_pan) = if dst_pan_present {
834            let (off, pan_be) = dec_try!(buf, off; decode_u16);
835            (off, Some(u16::from_be(pan_be)))
836        } else {
837            (off, None)
838        };
839        let (off, dst_addr) = dec_try!(buf, off; MacAddress::decode, dst_mode);
840        let (off, src_pan) = if src_pan_present {
841            let (off, pan_be) = dec_try!(buf, off; decode_u16);
842            (off, Some(u16::from_be(pan_be)))
843        } else {
844            if src_pan_dropped {
845                // If the src pan has been omitted as set above, then the dst
846                // pan must be present, otherwise the modes and compression flag
847                // were set wrong and the header is invalid
848                (off, Some(stream_from_option!(dst_pan)))
849            } else {
850                (off, None)
851            }
852        };
853        let (off, src_addr) = dec_try!(buf, off; MacAddress::decode, src_mode);
854
855        stream_done!(off, (dst_pan, dst_addr, src_pan, src_addr));
856    }
857}