1use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
10
11use byteorder::{BigEndian, ByteOrder};
12
13use crate::message::{StunParseError, TransactionId, MAGIC_COOKIE};
14use crate::AddressFamily;
15
16use super::{check_len, AttributeType, RawAttribute};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct MappedSocketAddr {
21 addr: SocketAddr,
22}
23
24impl MappedSocketAddr {
25 pub fn new(addr: SocketAddr) -> Self {
27 Self { addr }
28 }
29
30 pub fn length(&self) -> u16 {
32 match self.addr {
33 SocketAddr::V4(_) => 8,
34 SocketAddr::V6(_) => 20,
35 }
36 }
37
38 pub fn to_raw(&self, atype: AttributeType) -> RawAttribute<'_> {
40 match self.addr {
41 SocketAddr::V4(_addr) => {
42 let mut buf = [0; 8];
43 self.write_into_unchecked(&mut buf);
44 RawAttribute::new(atype, &buf).into_owned()
45 }
46 SocketAddr::V6(_addr) => {
47 let mut buf = [0; 20];
48 self.write_into_unchecked(&mut buf);
49 RawAttribute::new(atype, &buf).into_owned()
50 }
51 }
52 }
53
54 pub fn from_raw(raw: &RawAttribute) -> Result<Self, StunParseError> {
56 if raw.value.len() < 4 {
57 return Err(StunParseError::Truncated {
58 expected: 4,
59 actual: raw.value.len(),
60 });
61 }
62 let port = BigEndian::read_u16(&raw.value[2..4]);
63 let family = AddressFamily::from_byte(raw.value[1])?;
64 let addr = match family {
65 AddressFamily::IPV4 => {
66 check_len(raw.value.len(), 8..=8)?;
68 IpAddr::V4(Ipv4Addr::from(BigEndian::read_u32(&raw.value[4..8])))
69 }
70 AddressFamily::IPV6 => {
71 check_len(raw.value.len(), 20..=20)?;
73 let mut octets = [0; 16];
74 octets.clone_from_slice(&raw.value[4..]);
75 IpAddr::V6(Ipv6Addr::from(octets))
76 }
77 };
78 Ok(Self {
79 addr: SocketAddr::new(addr, port),
80 })
81 }
82
83 pub fn addr(&self) -> SocketAddr {
85 self.addr
86 }
87
88 pub fn write_into_unchecked(&self, dest: &mut [u8]) {
90 match self.addr {
91 SocketAddr::V4(addr) => {
92 dest[0] = 0x0;
93 dest[1] = AddressFamily::IPV4.to_byte();
94 BigEndian::write_u16(&mut dest[2..4], addr.port());
95 let octets = u32::from(*addr.ip());
96 BigEndian::write_u32(&mut dest[4..8], octets);
97 }
98 SocketAddr::V6(addr) => {
99 dest[0] = 0x0;
100 dest[1] = AddressFamily::IPV6.to_byte();
101 BigEndian::write_u16(&mut dest[2..4], addr.port());
102 let octets = u128::from(*addr.ip());
103 BigEndian::write_u128(&mut dest[4..20], octets);
104 }
105 }
106 }
107}
108
109impl core::fmt::Display for MappedSocketAddr {
110 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111 match self.addr {
112 SocketAddr::V4(addr) => write!(f, "{addr:?}"),
113 SocketAddr::V6(addr) => write!(f, "{addr:?}"),
114 }
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
122#[repr(transparent)]
123pub struct XorSocketAddr {
124 pub addr: MappedSocketAddr,
126}
127
128impl XorSocketAddr {
129 pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
131 Self {
132 addr: MappedSocketAddr::new(XorSocketAddr::xor_addr(addr, transaction)),
133 }
134 }
135
136 pub fn length(&self) -> u16 {
138 self.addr.length()
139 }
140
141 pub fn to_raw(&self, atype: AttributeType) -> RawAttribute<'_> {
143 self.addr.to_raw(atype)
144 }
145
146 pub fn from_raw(raw: &RawAttribute) -> Result<Self, StunParseError> {
148 let addr = MappedSocketAddr::from_raw(raw)?;
149 Ok(Self { addr })
150 }
151
152 pub fn xor_addr(addr: SocketAddr, transaction: TransactionId) -> SocketAddr {
154 match addr {
155 SocketAddr::V4(addr) => {
156 let port = addr.port() ^ (MAGIC_COOKIE >> 16) as u16;
157 let const_octets = MAGIC_COOKIE.to_be_bytes();
158 let addr_octets = addr.ip().octets();
159 let octets = bytewise_xor!(4, const_octets, addr_octets, 0);
160 SocketAddr::new(IpAddr::V4(Ipv4Addr::from(octets)), port)
161 }
162 SocketAddr::V6(addr) => {
163 let port = addr.port() ^ (MAGIC_COOKIE >> 16) as u16;
164 let transaction: u128 = transaction.into();
165 let const_octets = ((MAGIC_COOKIE as u128) << 96
166 | (transaction & 0x0000_0000_ffff_ffff_ffff_ffff_ffff_ffff))
167 .to_be_bytes();
168 let addr_octets = addr.ip().octets();
169 let octets = bytewise_xor!(16, const_octets, addr_octets, 0);
170 SocketAddr::new(IpAddr::V6(Ipv6Addr::from(octets)), port)
171 }
172 }
173 }
174
175 pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
177 XorSocketAddr::xor_addr(self.addr.addr(), transaction)
178 }
179
180 pub fn write_into_unchecked(&self, dest: &mut [u8]) {
182 self.addr.write_into_unchecked(dest)
183 }
184}
185
186impl core::fmt::Display for XorSocketAddr {
187 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
188 match self.addr.addr() {
189 SocketAddr::V4(_) => write!(f, "{:?}", self.addr(0x0.into())),
190 SocketAddr::V6(addr) => write!(f, "XOR({addr:?})"),
191 }
192 }
193}
194
195#[cfg(test)]
196pub(crate) mod tests {
197 use super::*;
198 use tracing::trace;
199
200 #[test]
201 fn mapped_address_ipv4() {
202 let addr = "192.168.0.1:3178".parse().unwrap();
203 let _log = crate::tests::test_init_log();
204 let data = [
205 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x0C, 0x6A, 0xC0, 0xA8, 0x00, 0x01,
206 ];
207 let mapped = MappedSocketAddr::from_raw(&RawAttribute::from_bytes(&data).unwrap()).unwrap();
208 trace!("mapped: {mapped}");
209 assert_eq!(mapped.addr(), addr);
210 }
211
212 #[test]
213 fn mapped_address_short() {
214 let _log = crate::tests::test_init_log();
215 let data = [0x00, 0x01, 0x00, 0x02, 0x00, 0x00];
216 assert!(matches!(
217 MappedSocketAddr::from_raw(&RawAttribute::from_bytes(&data).unwrap()),
218 Err(StunParseError::Truncated {
219 expected: 4,
220 actual: 2
221 })
222 ));
223 }
224
225 #[test]
226 fn mapped_address_unknown_family() {
227 let _log = crate::tests::test_init_log();
228 let data = [0x00, 0x01, 0x00, 0x04, 0x00, 0x99, 0x00, 0x00];
229 assert!(matches!(
230 MappedSocketAddr::from_raw(&RawAttribute::from_bytes(&data).unwrap()),
231 Err(StunParseError::InvalidAttributeData)
232 ));
233 }
234}