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