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