1#[cfg(test)]
2mod xoraddr_test;
3
4use crate::addr::*;
5use crate::attributes::*;
6use crate::checks::*;
7use crate::errors::*;
8use crate::message::*;
9
10use util::Error;
11
12use std::fmt;
13use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
14
15use std::mem;
16
17const WORD_SIZE: usize = mem::size_of::<usize>();
18
19fn safe_xorbytes(dst: &mut [u8], a: &[u8], b: &[u8]) -> usize {
47 let mut n = a.len();
48 if b.len() < n {
49 n = b.len();
50 }
51 if dst.len() < n {
52 n = dst.len();
53 }
54 for i in 0..n {
55 dst[i] = a[i] ^ b[i];
56 }
57 n
58}
59
60fn xor_bytes(dst: &mut [u8], a: &[u8], b: &[u8]) -> usize {
63 safe_xorbytes(dst, a, b)
67}
68
69pub struct XORMappedAddress {
73 pub ip: IpAddr,
74 pub port: u16,
75}
76
77impl Default for XORMappedAddress {
78 fn default() -> Self {
79 XORMappedAddress {
80 ip: IpAddr::V4(Ipv4Addr::from(0)),
81 port: 0,
82 }
83 }
84}
85
86impl fmt::Display for XORMappedAddress {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 let family = match self.ip {
89 IpAddr::V4(_) => FAMILY_IPV4,
90 IpAddr::V6(_) => FAMILY_IPV6,
91 };
92 if family == FAMILY_IPV4 {
93 write!(f, "{}:{}", self.ip, self.port)
94 } else {
95 write!(f, "[{}]:{}", self.ip, self.port)
96 }
97 }
98}
99
100impl Setter for XORMappedAddress {
101 fn add_to(&self, m: &mut Message) -> Result<(), Error> {
104 self.add_to_as(m, ATTR_XORMAPPED_ADDRESS)
105 }
106}
107
108impl Getter for XORMappedAddress {
109 fn get_from(&mut self, m: &Message) -> Result<(), Error> {
131 self.get_from_as(m, ATTR_XORMAPPED_ADDRESS)
132 }
133}
134
135impl XORMappedAddress {
136 pub fn add_to_as(&self, m: &mut Message, t: AttrType) -> Result<(), Error> {
138 let (family, ip_len, ip) = match self.ip {
139 IpAddr::V4(ipv4) => (FAMILY_IPV4, IPV4LEN, ipv4.octets().to_vec()),
140 IpAddr::V6(ipv6) => (FAMILY_IPV6, IPV6LEN, ipv6.octets().to_vec()),
141 };
142
143 let mut value = vec![0; 32 + 128];
144 let mut xor_value = vec![0; IPV6LEN];
146 xor_value[4..].copy_from_slice(&m.transaction_id.0);
147 xor_value[0..4].copy_from_slice(&MAGIC_COOKIE.to_be_bytes());
148 value[0..2].copy_from_slice(&family.to_be_bytes());
149 value[2..4].copy_from_slice(&(self.port ^ (MAGIC_COOKIE >> 16) as u16).to_be_bytes());
150 xor_bytes(&mut value[4..4 + ip_len], &ip, &xor_value);
151 m.add(t, &value[..4 + ip_len]);
152 Ok(())
153 }
154
155 pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<(), Error> {
158 let v = m.get(t)?;
159 if v.len() <= 4 {
160 return Err(ERR_UNEXPECTED_EOF.clone());
161 }
162
163 let family = u16::from_be_bytes([v[0], v[1]]);
164 if family != FAMILY_IPV6 && family != FAMILY_IPV4 {
165 return Err(Error::new(format!("bad value {}", family)));
166 }
167
168 check_overflow(
169 t,
170 v[4..].len(),
171 if family == FAMILY_IPV4 {
172 IPV4LEN
173 } else {
174 IPV6LEN
175 },
176 )?;
177 self.port = u16::from_be_bytes([v[2], v[3]]) ^ (MAGIC_COOKIE >> 16) as u16;
178 let mut xor_value = vec![0; 4 + TRANSACTION_ID_SIZE];
179 xor_value[0..4].copy_from_slice(&MAGIC_COOKIE.to_be_bytes());
180 xor_value[4..].copy_from_slice(&m.transaction_id.0);
181
182 if family == FAMILY_IPV6 {
183 let mut ip = [0; IPV6LEN];
184 xor_bytes(&mut ip, &v[4..], &xor_value);
185 self.ip = IpAddr::V6(Ipv6Addr::from(ip));
186 } else {
187 let mut ip = [0; IPV4LEN];
188 xor_bytes(&mut ip, &v[4..], &xor_value);
189 self.ip = IpAddr::V4(Ipv4Addr::from(ip));
190 };
191
192 Ok(())
193 }
194}