55//! [`Header`]: struct.Header.html
66
77use byte:: { check_len, BytesExt , TryRead , TryWrite , LE } ;
8+ use cipher:: { consts:: U16 , BlockCipher , NewBlockCipher } ;
89use hash32_derive:: Hash32 ;
910
10- use super :: frame_control:: * ;
11- pub use super :: frame_control:: { AddressMode , FrameType , FrameVersion , Security } ;
11+ pub use super :: frame_control:: { AddressMode , FrameType , FrameVersion } ;
1212use super :: DecodeError ;
13+ use super :: {
14+ frame_control:: { mask, offset} ,
15+ security:: { KeyDescriptorLookup , SecurityContext } ,
16+ } ;
17+ use super :: { security:: AuxiliarySecurityHeader , EncodeError } ;
1318
1419/// MAC frame header
1520///
@@ -22,9 +27,6 @@ pub struct Header {
2227 /// Frame Type
2328 pub frame_type : FrameType ,
2429
25- /// Auxiliary Security header
26- pub security : Security ,
27-
2830 /// Frame Pending
2931 ///
3032 /// The Frame Pending field shall be set to `true` if the device sending the frame has more data
@@ -67,6 +69,39 @@ pub struct Header {
6769
6870 /// Source Address
6971 pub source : Option < Address > ,
72+
73+ /// Auxiliary security header. If security is enabled in this header,
74+ /// this field will be Some, else it will be None
75+ pub auxiliary_security_header : Option < AuxiliarySecurityHeader > ,
76+ }
77+
78+ impl Header {
79+ /// Get the size of this header in octets
80+ pub fn get_octet_size ( & self ) -> usize {
81+ // Frame control + sequence number
82+ let mut len = 3 ;
83+
84+ for i in [ self . destination , self . source ] . iter ( ) {
85+ match i {
86+ Some ( addr) => {
87+ // pan ID
88+ len += 2 ;
89+ // Address length
90+ match addr {
91+ Address :: Short ( ..) => len += 2 ,
92+ Address :: Extended ( ..) => len += 8 ,
93+ }
94+ }
95+ _ => { }
96+ }
97+ }
98+ len
99+ }
100+
101+ /// Whether this header has security enabled
102+ pub fn has_security ( & self ) -> bool {
103+ self . auxiliary_security_header . is_some ( )
104+ }
70105}
71106
72107impl TryRead < ' _ > for Header {
@@ -97,11 +132,7 @@ impl TryRead<'_> for Header {
97132 let src_addr_mode = AddressMode :: from_bits ( src_addr_mode) ?;
98133
99134 // make bool values
100- let security = if security > 0 {
101- return Err ( DecodeError :: SecurityNotSupported . into ( ) ) ;
102- } else {
103- Security :: None
104- } ;
135+ let security = security > 0 ;
105136 let frame_pending = frame_pending > 0 ;
106137 let ack_request = ack_request > 0 ;
107138 let pan_id_compress = pan_id_compress > 0 ;
@@ -148,31 +179,46 @@ impl TryRead<'_> for Header {
148179 }
149180 } ;
150181
182+ let auxiliary_security_header = match security {
183+ true => Some ( bytes. read ( offset) ?) ,
184+ false => None ,
185+ } ;
186+
151187 let header = Header {
152188 frame_type,
153- security,
154189 frame_pending,
155190 ack_request,
156191 pan_id_compress,
157192 version,
158-
159193 seq,
160194 destination,
161195 source,
196+ auxiliary_security_header,
162197 } ;
163198
164199 Ok ( ( header, * offset) )
165200 }
166201}
167202
168- impl TryWrite for Header {
169- fn try_write ( self , bytes : & mut [ u8 ] , _ctx : ( ) ) -> byte:: Result < usize > {
203+ impl < AEADBLKCIPH , KEYDESCLO > TryWrite < & Option < & mut SecurityContext < AEADBLKCIPH , KEYDESCLO > > >
204+ for Header
205+ where
206+ AEADBLKCIPH : NewBlockCipher + BlockCipher < BlockSize = U16 > ,
207+ KEYDESCLO : KeyDescriptorLookup < AEADBLKCIPH :: KeySize > ,
208+ {
209+ fn try_write (
210+ self ,
211+ bytes : & mut [ u8 ] ,
212+ sec_ctx : & Option < & mut SecurityContext < AEADBLKCIPH , KEYDESCLO > > ,
213+ ) -> byte:: Result < usize > {
170214 let offset = & mut 0 ;
171215 let dest_addr_mode = AddressMode :: from ( self . destination ) ;
172216 let src_addr_mode = AddressMode :: from ( self . source ) ;
173217
218+ let security = self . auxiliary_security_header . is_some ( ) ;
219+
174220 let frame_control_raw = ( self . frame_type as u16 ) << offset:: FRAME_TYPE
175- | ( self . security as u16 ) << offset:: SECURITY
221+ | ( security as u16 ) << offset:: SECURITY
176222 | ( self . frame_pending as u16 ) << offset:: PENDING
177223 | ( self . ack_request as u16 ) << offset:: ACK
178224 | ( self . pan_id_compress as u16 ) << offset:: PAN_ID_COMPRESS
@@ -202,6 +248,20 @@ impl TryWrite for Header {
202248 }
203249 ( None , false ) => ( ) ,
204250 }
251+
252+ if security && sec_ctx. is_none ( ) {
253+ return Err ( EncodeError :: MissingSecurityCtx ) ?;
254+ } else if security {
255+ match self . auxiliary_security_header {
256+ Some ( aux_sec_head) => match sec_ctx {
257+ Some ( sec_ctx) => {
258+ bytes. write_with ( offset, aux_sec_head, sec_ctx) ?;
259+ }
260+ None => return Err ( EncodeError :: UnknownError ) ?,
261+ } ,
262+ None => return Err ( EncodeError :: UnknownError ) ?,
263+ }
264+ }
205265 Ok ( * offset)
206266 }
207267}
0 commit comments