1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#[cfg(test)]
mod addr_test;
use crate::attributes::*;
use crate::error::*;
use crate::message::*;
use anyhow::Result;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
pub(crate) const FAMILY_IPV4: u16 = 0x01;
pub(crate) const FAMILY_IPV6: u16 = 0x02;
pub(crate) const IPV4LEN: usize = 4;
pub(crate) const IPV6LEN: usize = 16;
pub struct MappedAddress {
pub ip: IpAddr,
pub port: u16,
}
impl fmt::Display for MappedAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let family = match self.ip {
IpAddr::V4(_) => FAMILY_IPV4,
IpAddr::V6(_) => FAMILY_IPV6,
};
if family == FAMILY_IPV4 {
write!(f, "{}:{}", self.ip, self.port)
} else {
write!(f, "[{}]:{}", self.ip, self.port)
}
}
}
impl Default for MappedAddress {
fn default() -> Self {
MappedAddress {
ip: IpAddr::V4(Ipv4Addr::from(0)),
port: 0,
}
}
}
impl Setter for MappedAddress {
fn add_to(&self, m: &mut Message) -> Result<()> {
self.add_to_as(m, ATTR_MAPPED_ADDRESS)
}
}
impl Getter for MappedAddress {
fn get_from(&mut self, m: &Message) -> Result<()> {
self.get_from_as(m, ATTR_MAPPED_ADDRESS)
}
}
impl MappedAddress {
pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<()> {
let v = m.get(t)?;
if v.len() <= 4 {
return Err(Error::ErrUnexpectedEof.into());
}
let family = u16::from_be_bytes([v[0], v[1]]);
if family != FAMILY_IPV6 && family != FAMILY_IPV4 {
return Err(Error::new(format!("bad value {}", family)).into());
}
self.port = u16::from_be_bytes([v[2], v[3]]);
if family == FAMILY_IPV6 {
let mut ip = [0; IPV6LEN];
let l = std::cmp::min(ip.len(), v[4..].len());
ip[..l].copy_from_slice(&v[4..4 + l]);
self.ip = IpAddr::V6(Ipv6Addr::from(ip));
} else {
let mut ip = [0; IPV4LEN];
let l = std::cmp::min(ip.len(), v[4..].len());
ip[..l].copy_from_slice(&v[4..4 + l]);
self.ip = IpAddr::V4(Ipv4Addr::from(ip));
};
Ok(())
}
pub fn add_to_as(&self, m: &mut Message, t: AttrType) -> Result<()> {
let family = match self.ip {
IpAddr::V4(_) => FAMILY_IPV4,
IpAddr::V6(_) => FAMILY_IPV6,
};
let mut value = vec![0u8; 4];
value[0..2].copy_from_slice(&family.to_be_bytes());
value[2..4].copy_from_slice(&self.port.to_be_bytes());
match self.ip {
IpAddr::V4(ipv4) => value.extend_from_slice(&ipv4.octets()),
IpAddr::V6(ipv6) => value.extend_from_slice(&ipv6.octets()),
};
m.add(t, &value);
Ok(())
}
}
pub type AlternateServer = MappedAddress;
pub type ResponseOrigin = MappedAddress;
pub type OtherAddress = MappedAddress;