1macro_rules! bytewise_xor {
116 ($size:literal, $a:expr, $b:expr, $default:literal) => {{
117 let mut arr = [$default; $size];
118 for (i, item) in arr.iter_mut().enumerate() {
119 *item = $a[i] ^ $b[i];
120 }
121 arr
122 }};
123}
124
125mod address;
126pub use address::{AddressFamily, MappedSocketAddr, XorSocketAddr};
127mod alternate;
128pub use alternate::{AlternateDomain, AlternateServer};
129mod error;
130pub use error::{ErrorCode, UnknownAttributes};
131mod ice;
132pub use ice::{IceControlled, IceControlling, Priority, UseCandidate};
133mod integrity;
134pub use integrity::{MessageIntegrity, MessageIntegritySha256};
135mod fingerprint;
136pub use fingerprint::Fingerprint;
137mod nonce;
138pub use nonce::Nonce;
139mod password_algorithm;
140pub use password_algorithm::{PasswordAlgorithm, PasswordAlgorithmValue, PasswordAlgorithms};
141mod realm;
142pub use realm::Realm;
143mod user;
144pub use user::{Userhash, Username};
145mod software;
146pub use software::Software;
147mod xor_addr;
148pub use xor_addr::XorMappedAddress;
149
150use crate::data::Data;
151use crate::message::{StunParseError, StunWriteError};
152
153use byteorder::{BigEndian, ByteOrder};
154
155use std::collections::HashMap;
156use std::sync::{Mutex, OnceLock};
157
158pub type AttributeDisplay =
166 fn(&RawAttribute<'_>, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result;
167static ATTRIBUTE_EXTERNAL_DISPLAY_IMPL: OnceLock<Mutex<HashMap<AttributeType, AttributeDisplay>>> =
168 OnceLock::new();
169
170pub fn add_display_impl(atype: AttributeType, imp: AttributeDisplay) {
173 let mut display_impls = ATTRIBUTE_EXTERNAL_DISPLAY_IMPL
174 .get_or_init(Default::default)
175 .lock()
176 .unwrap();
177 display_impls.insert(atype, imp);
178}
179
180#[macro_export]
222macro_rules! attribute_display {
223 ($typ:ty) => {{
224 let imp = |attr: &$crate::attribute::RawAttribute<'_>,
225 f: &mut std::fmt::Formatter<'_>|
226 -> std::fmt::Result {
227 if let Ok(attr) = <$typ>::from_raw_ref(attr) {
228 write!(f, "{}", attr)
229 } else {
230 write!(
231 f,
232 "{}(Malformed): len: {}, data: {:?})",
233 attr.get_type(),
234 attr.header.length(),
235 attr.value
236 )
237 }
238 };
239
240 $crate::attribute::add_display_impl(<$typ>::TYPE, imp);
241 }};
242}
243
244static ATTRIBUTE_TYPE_NAME_MAP: OnceLock<Mutex<HashMap<AttributeType, &'static str>>> =
245 OnceLock::new();
246
247#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
249pub struct AttributeType(u16);
250
251impl std::fmt::Display for AttributeType {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 write!(f, "{}({:#x}: {})", self.0, self.0, self.name())
254 }
255}
256
257impl AttributeType {
258 pub fn add_name(self, name: &'static str) {
260 let mut anames = ATTRIBUTE_TYPE_NAME_MAP
261 .get_or_init(Default::default)
262 .lock()
263 .unwrap();
264 anames.insert(self, name);
265 }
266
267 pub const fn new(val: u16) -> Self {
277 Self(val)
278 }
279
280 pub fn value(&self) -> u16 {
290 self.0
291 }
292
293 pub fn name(self) -> &'static str {
301 match self {
302 AttributeType(0x0001) => "MAPPED-ADDRESS",
303 Username::TYPE => "USERNAME",
304 MessageIntegrity::TYPE => "MESSAGE-INTEGRITY",
305 ErrorCode::TYPE => "ERROR-CODE",
306 UnknownAttributes::TYPE => "UNKNOWN-ATTRIBUTES",
307 Realm::TYPE => "REALM",
308 Nonce::TYPE => "NONCE",
309 MessageIntegritySha256::TYPE => "MESSAGE-INTEGRITY-SHA256",
310 PasswordAlgorithm::TYPE => "PASSWORD-ALGORITHM",
311 Userhash::TYPE => "USERHASH",
312 XorMappedAddress::TYPE => "XOR-MAPPED-ADDRESS",
313 PasswordAlgorithms::TYPE => "PASSWORD_ALGORITHMS",
314 AlternateDomain::TYPE => "ALTERNATE-DOMAIN",
315 Software::TYPE => "SOFTWARE",
316 AlternateServer::TYPE => "ALTERNATE-SERVER",
317 Fingerprint::TYPE => "FINGERPRINT",
318 Priority::TYPE => "PRIORITY",
319 UseCandidate::TYPE => "USE-CANDIDATE",
320 IceControlled::TYPE => "ICE-CONTROLLED",
321 IceControlling::TYPE => "ICE-CONTROLLING",
322 _ => {
323 let anames = ATTRIBUTE_TYPE_NAME_MAP
324 .get_or_init(Default::default)
325 .lock()
326 .unwrap();
327 if let Some(name) = anames.get(&self) {
328 name
329 } else {
330 "unknown"
331 }
332 }
333 }
334 }
335
336 pub fn comprehension_required(self) -> bool {
347 self.0 < 0x8000
348 }
349}
350impl From<u16> for AttributeType {
351 fn from(f: u16) -> Self {
352 Self::new(f)
353 }
354}
355impl From<AttributeType> for u16 {
356 fn from(f: AttributeType) -> Self {
357 f.0
358 }
359}
360
361#[derive(Debug, Copy, Clone, PartialEq, Eq)]
363pub struct AttributeHeader {
364 atype: AttributeType,
365 length: u16,
366}
367
368impl AttributeHeader {
369 fn parse(data: &[u8]) -> Result<Self, StunParseError> {
370 if data.len() < 4 {
371 return Err(StunParseError::Truncated {
372 expected: 4,
373 actual: data.len(),
374 });
375 }
376 let ret = Self {
377 atype: BigEndian::read_u16(&data[0..2]).into(),
378 length: BigEndian::read_u16(&data[2..4]),
379 };
380 Ok(ret)
381 }
382
383 fn to_bytes(self) -> Vec<u8> {
384 let mut ret = vec![0; 4];
385 self.write_into(&mut ret);
386 ret
387 }
388
389 fn write_into(&self, ret: &mut [u8]) {
390 BigEndian::write_u16(&mut ret[0..2], self.atype.into());
391 BigEndian::write_u16(&mut ret[2..4], self.length);
392 }
393
394 pub fn get_type(&self) -> AttributeType {
396 self.atype
397 }
398
399 pub fn length(&self) -> u16 {
401 self.length
402 }
403}
404impl From<AttributeHeader> for Vec<u8> {
405 fn from(f: AttributeHeader) -> Self {
406 f.to_bytes()
407 }
408}
409impl TryFrom<&[u8]> for AttributeHeader {
410 type Error = StunParseError;
411
412 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
413 AttributeHeader::parse(value)
414 }
415}
416
417pub trait AttributeStaticType {
419 const TYPE: AttributeType;
421}
422
423pub trait Attribute: std::fmt::Debug + std::marker::Sync {
425 fn get_type(&self) -> AttributeType;
427
428 fn length(&self) -> u16;
431}
432
433pub trait AttributeFromRaw<'a>: Attribute {
435 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
437 where
438 Self: Sized;
439
440 fn from_raw(raw: RawAttribute<'a>) -> Result<Self, StunParseError>
442 where
443 Self: Sized,
444 {
445 Self::from_raw_ref(&raw)
446 }
447}
448
449fn padded_attr_len(len: usize) -> usize {
450 if len % 4 == 0 {
451 len
452 } else {
453 len + 4 - len % 4
454 }
455}
456
457pub trait AttributeExt {
459 fn padded_len(&self) -> usize;
462}
463
464impl<A: Attribute + ?Sized> AttributeExt for A {
465 fn padded_len(&self) -> usize {
466 4 + padded_attr_len(self.length() as usize)
467 }
468}
469
470pub trait AttributeWrite: Attribute {
472 fn write_into_unchecked(&self, dest: &mut [u8]);
476 fn to_raw(&self) -> RawAttribute;
478}
479
480pub trait AttributeWriteExt: AttributeWrite {
483 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize;
488 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
491 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError>;
494}
495
496impl<A: AttributeWrite + ?Sized> AttributeWriteExt for A {
497 fn write_header(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
498 if dest.len() < 4 {
499 return Err(StunWriteError::TooSmall {
500 expected: 4,
501 actual: dest.len(),
502 });
503 }
504 self.write_header_unchecked(dest);
505 Ok(4)
506 }
507 fn write_header_unchecked(&self, dest: &mut [u8]) -> usize {
508 AttributeHeader {
509 atype: self.get_type(),
510 length: self.length(),
511 }
512 .write_into(dest);
513 4
514 }
515
516 fn write_into(&self, dest: &mut [u8]) -> Result<usize, StunWriteError> {
517 let len = self.padded_len();
518 if len > dest.len() {
519 return Err(StunWriteError::TooSmall {
520 expected: len,
521 actual: dest.len(),
522 });
523 }
524 self.write_into_unchecked(dest);
525 Ok(len)
526 }
527}
528
529#[derive(Debug, Clone, PartialEq, Eq)]
531pub struct RawAttribute<'a> {
532 pub header: AttributeHeader,
534 pub value: Data<'a>,
536}
537
538macro_rules! display_attr {
539 ($this:ident, $f:ident, $CamelType:ty) => {{
540 if let Ok(attr) = <$CamelType>::from_raw_ref($this) {
541 write!($f, "{}", attr)
542 } else {
543 write!(
544 $f,
545 "{}(Malformed): len: {}, data: {:?})",
546 $this.get_type(),
547 $this.header.length(),
548 $this.value
549 )
550 }
551 }};
552}
553
554impl std::fmt::Display for RawAttribute<'_> {
555 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
556 match self.get_type() {
558 Username::TYPE => display_attr!(self, f, Username),
559 MessageIntegrity::TYPE => display_attr!(self, f, MessageIntegrity),
560 ErrorCode::TYPE => display_attr!(self, f, ErrorCode),
561 UnknownAttributes::TYPE => display_attr!(self, f, UnknownAttributes),
562 Realm::TYPE => display_attr!(self, f, Realm),
563 Nonce::TYPE => display_attr!(self, f, Nonce),
564 MessageIntegritySha256::TYPE => {
565 display_attr!(self, f, MessageIntegritySha256)
566 }
567 PasswordAlgorithm::TYPE => display_attr!(self, f, PasswordAlgorithm),
568 XorMappedAddress::TYPE => display_attr!(self, f, XorMappedAddress),
570 PasswordAlgorithms::TYPE => display_attr!(self, f, PasswordAlgorithms),
571 AlternateDomain::TYPE => display_attr!(self, f, AlternateDomain),
572 Software::TYPE => display_attr!(self, f, Software),
573 AlternateServer::TYPE => display_attr!(self, f, AlternateServer),
574 Fingerprint::TYPE => display_attr!(self, f, Fingerprint),
575 Priority::TYPE => display_attr!(self, f, Priority),
576 UseCandidate::TYPE => display_attr!(self, f, UseCandidate),
577 IceControlled::TYPE => display_attr!(self, f, IceControlled),
578 IceControlling::TYPE => display_attr!(self, f, IceControlling),
579 _ => {
580 let mut display_impls = ATTRIBUTE_EXTERNAL_DISPLAY_IMPL
581 .get_or_init(|| Default::default())
582 .lock()
583 .unwrap();
584 if let Some(imp) = display_impls.get_mut(&self.get_type()) {
585 imp(self, f)
586 } else {
587 write!(
588 f,
589 "RawAttribute (type: {:?}, len: {}, data: {:?})",
590 self.header.get_type(),
591 self.header.length(),
592 &self.value
593 )
594 }
595 }
596 }
597 }
598}
599
600impl<'a> RawAttribute<'a> {
601 pub fn new(atype: AttributeType, data: &'a [u8]) -> Self {
603 Self {
604 header: AttributeHeader {
605 atype,
606 length: data.len() as u16,
607 },
608 value: data.into(),
609 }
610 }
611
612 pub fn new_owned(atype: AttributeType, data: Box<[u8]>) -> Self {
614 Self {
615 header: AttributeHeader {
616 atype,
617 length: data.len() as u16,
618 },
619 value: data.into(),
620 }
621 }
622
623 pub fn from_bytes(data: &'a [u8]) -> Result<Self, StunParseError> {
635 let header = AttributeHeader::parse(data)?;
636 if header.length() > (data.len() - 4) as u16 {
638 return Err(StunParseError::Truncated {
639 expected: header.length() as usize,
640 actual: data.len() - 4,
641 });
642 }
643 Ok(Self {
644 header,
645 value: Data::Borrowed(data[4..header.length() as usize + 4].into()),
646 })
647 }
648
649 pub fn to_bytes(&self) -> Vec<u8> {
659 let mut vec = Vec::with_capacity(self.padded_len());
660 let mut header_bytes = [0; 4];
661 self.header.write_into(&mut header_bytes);
662 vec.extend(&header_bytes);
663 vec.extend(&*self.value);
664 let len = vec.len();
665 if len % 4 != 0 {
666 vec.resize(len + 4 - (len % 4), 0);
668 }
669 vec
670 }
671
672 pub fn check_type_and_len(
674 &self,
675 atype: AttributeType,
676 allowed_range: impl std::ops::RangeBounds<usize>,
677 ) -> Result<(), StunParseError> {
678 if self.header.get_type() != atype {
679 return Err(StunParseError::WrongAttributeImplementation);
680 }
681 check_len(self.value.len(), allowed_range)
682 }
683
684 pub fn into_owned<'b>(self) -> RawAttribute<'b> {
686 RawAttribute {
687 header: self.header,
688 value: self.value.into_owned(),
689 }
690 }
691}
692
693impl Attribute for RawAttribute<'_> {
694 fn get_type(&self) -> AttributeType {
696 self.header.get_type()
697 }
698
699 fn length(&self) -> u16 {
701 self.value.len() as u16
702 }
703}
704
705impl<'a> AttributeWrite for RawAttribute<'a> {
706 fn write_into_unchecked(&self, dest: &mut [u8]) {
708 let len = self.padded_len();
709 self.header.write_into(dest);
710 let mut offset = 4;
711 dest[offset..offset + self.value.len()].copy_from_slice(&self.value);
712 offset += self.value.len();
713 if len - offset > 0 {
714 dest[offset..len].fill(0);
715 }
716 }
717
718 fn to_raw(&self) -> RawAttribute<'a> {
719 self.clone()
720 }
721}
722
723impl<'a, A: AttributeWrite> From<&'a A> for RawAttribute<'a> {
724 fn from(value: &'a A) -> Self {
725 value.to_raw()
726 }
727}
728
729fn check_len(
730 len: usize,
731 allowed_range: impl std::ops::RangeBounds<usize>,
732) -> Result<(), StunParseError> {
733 match allowed_range.start_bound() {
734 std::ops::Bound::Unbounded => (),
735 std::ops::Bound::Included(start) => {
736 if len < *start {
737 return Err(StunParseError::Truncated {
738 expected: *start,
739 actual: len,
740 });
741 }
742 }
743 std::ops::Bound::Excluded(start) => {
744 if len <= *start {
745 return Err(StunParseError::Truncated {
746 expected: start + 1,
747 actual: len,
748 });
749 }
750 }
751 }
752 match allowed_range.end_bound() {
753 std::ops::Bound::Unbounded => (),
754 std::ops::Bound::Included(end) => {
755 if len > *end {
756 return Err(StunParseError::TooLarge {
757 expected: *end,
758 actual: len,
759 });
760 }
761 }
762 std::ops::Bound::Excluded(end) => {
763 if len >= *end {
764 return Err(StunParseError::TooLarge {
765 expected: *end - 1,
766 actual: len,
767 });
768 }
769 }
770 }
771 Ok(())
772}
773
774impl From<RawAttribute<'_>> for Vec<u8> {
775 fn from(f: RawAttribute) -> Self {
776 f.to_bytes()
777 }
778}
779
780#[cfg(test)]
781mod tests {
782 use super::*;
783
784 #[test]
785 fn attribute_type() {
786 let _log = crate::tests::test_init_log();
787 let atype = ErrorCode::TYPE;
788 let anum: u16 = atype.into();
789 assert_eq!(atype, anum.into());
790 }
791
792 #[test]
793 fn short_attribute_header() {
794 let _log = crate::tests::test_init_log();
795 let data = [0; 1];
796 let res: Result<AttributeHeader, _> = data.as_ref().try_into();
798 assert!(res.is_err());
799 }
800
801 #[test]
802 fn raw_attribute_construct() {
803 let _log = crate::tests::test_init_log();
804 let a = RawAttribute::new(1.into(), &[80, 160]);
805 assert_eq!(a.get_type(), 1.into());
806 let bytes: Vec<_> = a.into();
807 assert_eq!(bytes, &[0, 1, 0, 2, 80, 160, 0, 0]);
808 let b = RawAttribute::from_bytes(bytes.as_ref()).unwrap();
809 assert_eq!(b.get_type(), 1.into());
810 }
811
812 #[test]
813 fn raw_attribute_encoding() {
814 let _log = crate::tests::test_init_log();
815 let orig = RawAttribute::new(1.into(), &[80, 160]);
816 assert_eq!(orig.get_type(), 1.into());
817 let mut data: Vec<_> = orig.into();
818 let len = data.len();
819 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 + 1);
821 assert!(matches!(
822 RawAttribute::from_bytes(data.as_ref()),
823 Err(StunParseError::Truncated {
824 expected: 5,
825 actual: 4
826 })
827 ));
828 }
829
830 #[test]
831 fn test_check_len() {
832 let _log = crate::tests::test_init_log();
833 assert!(check_len(4, ..).is_ok());
834 assert!(check_len(4, 0..).is_ok());
835 assert!(check_len(4, 0..8).is_ok());
836 assert!(check_len(4, 0..=8).is_ok());
837 assert!(check_len(4, ..=8).is_ok());
838 assert!(matches!(
839 check_len(4, ..4),
840 Err(StunParseError::TooLarge {
841 expected: 3,
842 actual: 4
843 })
844 ));
845 assert!(matches!(
846 check_len(4, 5..),
847 Err(StunParseError::Truncated {
848 expected: 5,
849 actual: 4
850 })
851 ));
852 assert!(matches!(
853 check_len(4, ..=3),
854 Err(StunParseError::TooLarge {
855 expected: 3,
856 actual: 4
857 })
858 ));
859 assert!(matches!(
860 check_len(
861 4,
862 (std::ops::Bound::Excluded(4), std::ops::Bound::Unbounded)
863 ),
864 Err(StunParseError::Truncated {
865 expected: 5,
866 actual: 4
867 })
868 ));
869 }
870
871 #[test]
872 fn test_external_display_impl() {
873 let _log = crate::tests::test_init_log();
874 let atype = AttributeType::new(0xFFFF);
875 let imp = |attr: &RawAttribute<'_>, f: &mut std::fmt::Formatter<'_>| -> std::fmt::Result {
876 write!(f, "Custom {}", attr.value[0])
877 };
878 add_display_impl(atype, imp);
879 let data = [4, 0];
880 let attr = RawAttribute::new(atype, &data);
881 let display_str = format!("{}", attr);
882 assert_eq!(display_str, "Custom 4");
883
884 atype.add_name("SOME-NAME");
885 assert_eq!(atype.name(), "SOME-NAME");
886
887 attribute_display!(Fingerprint);
888 }
889}