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,
25 pub port: u16,
27}
28
29impl fmt::Display for MappedAddress {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self.ip {
32 IpAddr::V4(ipv4) => write!(f, "{}:{}", ipv4, self.port),
33 IpAddr::V6(ipv6) => write!(f, "[{}]:{}", ipv6, self.port),
34 }
35 }
36}
37
38impl Default for MappedAddress {
39 fn default() -> Self {
40 MappedAddress {
41 ip: IpAddr::V4(Ipv4Addr::from(0)),
42 port: 0,
43 }
44 }
45}
46
47impl Setter for MappedAddress {
48 fn add_to(&self, m: &mut Message) -> Result<()> {
50 self.add_to_as(m, ATTR_MAPPED_ADDRESS)
51 }
52}
53
54impl Getter for MappedAddress {
55 fn get_from(&mut self, m: &Message) -> Result<()> {
57 self.get_from_as(m, ATTR_MAPPED_ADDRESS)
58 }
59}
60
61impl MappedAddress {
62 pub fn get_from_as(&mut self, m: &Message, t: AttrType) -> Result<()> {
64 let v = m.get(t)?;
65 if v.len() <= 4 {
66 return Err(Error::ErrUnexpectedEof);
67 }
68
69 let family = u16::from_be_bytes([v[0], v[1]]);
70 if family != FAMILY_IPV6 && family != FAMILY_IPV4 {
71 return Err(Error::Other(format!("bad value {family}")));
72 }
73 self.port = u16::from_be_bytes([v[2], v[3]]);
74
75 if family == FAMILY_IPV6 {
76 let mut ip = [0; IPV6LEN];
77 let l = std::cmp::min(ip.len(), v[4..].len());
78 ip[..l].copy_from_slice(&v[4..4 + l]);
79 self.ip = IpAddr::V6(Ipv6Addr::from(ip));
80 } else {
81 let mut ip = [0; IPV4LEN];
82 let l = std::cmp::min(ip.len(), v[4..].len());
83 ip[..l].copy_from_slice(&v[4..4 + l]);
84 self.ip = IpAddr::V4(Ipv4Addr::from(ip));
85 };
86
87 Ok(())
88 }
89
90 pub fn add_to_as(&self, m: &mut Message, t: AttrType) -> Result<()> {
92 let family = match self.ip {
93 IpAddr::V4(_) => FAMILY_IPV4,
94 IpAddr::V6(_) => FAMILY_IPV6,
95 };
96
97 let mut value = vec![0u8; 4];
98 value[0..2].copy_from_slice(&family.to_be_bytes());
100 value[2..4].copy_from_slice(&self.port.to_be_bytes());
101
102 match self.ip {
103 IpAddr::V4(ipv4) => value.extend_from_slice(&ipv4.octets()),
104 IpAddr::V6(ipv6) => value.extend_from_slice(&ipv6.octets()),
105 };
106
107 m.add(t, &value);
108 Ok(())
109 }
110}
111
112pub type AlternateServer = MappedAddress;
116
117pub type ResponseOrigin = MappedAddress;
121
122pub type OtherAddress = MappedAddress;