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