linkerd2_proxy_api/
net.rs

1use std::convert::{TryFrom, TryInto};
2use thiserror::Error;
3
4include!("gen/io.linkerd.proxy.net.rs");
5
6/// Indicates an IP address could not be decoded.
7#[derive(Clone, Debug, Error)]
8#[error("invalid IP address")]
9pub struct InvalidIpAddress;
10
11/// Indicates an IP address could not be decoded.
12#[derive(Clone, Debug, Error)]
13pub enum InvalidIpNetwork {
14    #[error("invalid IP address")]
15    Ip(#[from] InvalidIpAddress),
16    #[error("invalid network prefix length")]
17    PrefixLen(#[from] ipnet::PrefixLenError),
18}
19
20// === impl IpAddress ===
21
22#[cfg(feature = "net")]
23impl TryFrom<IpAddress> for std::net::IpAddr {
24    type Error = InvalidIpAddress;
25
26    fn try_from(ip: IpAddress) -> Result<Self, Self::Error> {
27        use ip_address::Ip;
28        match ip.ip {
29            Some(Ip::Ipv4(v4)) => Ok(std::net::IpAddr::V4(v4.into())),
30            Some(Ip::Ipv6(v6)) => Ok(std::net::IpAddr::V6(v6.into())),
31            None => Err(InvalidIpAddress),
32        }
33    }
34}
35
36#[cfg(feature = "net")]
37impl<T> From<T> for IpAddress
38where
39    ip_address::Ip: From<T>,
40{
41    #[inline]
42    fn from(ip: T) -> Self {
43        Self {
44            ip: Some(ip.into()),
45        }
46    }
47}
48
49impl From<std::net::IpAddr> for IpAddress {
50    fn from(ip: std::net::IpAddr) -> Self {
51        match ip {
52            std::net::IpAddr::V4(v4) => Self {
53                ip: Some(v4.into()),
54            },
55            std::net::IpAddr::V6(v6) => Self {
56                ip: Some(v6.into()),
57            },
58        }
59    }
60}
61
62impl From<[u8; 4]> for ip_address::Ip {
63    fn from(octets: [u8; 4]) -> Self {
64        ip_address::Ip::Ipv4(
65            u32::from(octets[0]) << 24
66                | u32::from(octets[1]) << 16
67                | u32::from(octets[2]) << 8
68                | u32::from(octets[3]),
69        )
70    }
71}
72
73// === impl IpNetwork ===
74
75impl TryFrom<IpNetwork> for ipnet::IpNet {
76    type Error = InvalidIpNetwork;
77
78    fn try_from(net: IpNetwork) -> Result<Self, Self::Error> {
79        let ip = net
80            .ip
81            .ok_or(InvalidIpNetwork::Ip(InvalidIpAddress))?
82            .try_into()
83            .map_err(InvalidIpNetwork::Ip)?;
84        let prefix_len = if (0..=u8::MAX as u32).contains(&net.prefix_len) {
85            net.prefix_len as u8
86        } else {
87            return Err(InvalidIpNetwork::PrefixLen(ipnet::PrefixLenError));
88        };
89        match ip {
90            std::net::IpAddr::V4(addr) => ipnet::Ipv4Net::new(addr, prefix_len)
91                .map(Into::into)
92                .map_err(InvalidIpNetwork::PrefixLen),
93            std::net::IpAddr::V6(addr) => ipnet::Ipv6Net::new(addr, prefix_len)
94                .map(Into::into)
95                .map_err(InvalidIpNetwork::PrefixLen),
96        }
97    }
98}
99
100impl<T> From<(T, u8)> for IpNetwork
101where
102    IpAddress: From<T>,
103{
104    #[inline]
105    fn from((ip, prefix_len): (T, u8)) -> Self {
106        Self {
107            ip: Some(ip.into()),
108            prefix_len: prefix_len.into(),
109        }
110    }
111}
112
113impl From<ipnet::IpNet> for IpNetwork {
114    fn from(net: ipnet::IpNet) -> Self {
115        IpNetwork {
116            ip: Some(net.addr().into()),
117            prefix_len: net.prefix_len().into(),
118        }
119    }
120}
121
122// === impl ip_address:Ip ===
123
124impl From<std::net::Ipv4Addr> for ip_address::Ip {
125    #[inline]
126    fn from(v4: std::net::Ipv4Addr) -> Self {
127        Self::from(v4.octets())
128    }
129}
130
131impl<T> From<T> for ip_address::Ip
132where
133    IPv6: From<T>,
134{
135    #[inline]
136    fn from(t: T) -> Self {
137        ip_address::Ip::Ipv6(IPv6::from(t))
138    }
139}
140
141// === impl IPv6 ===
142
143impl From<[u8; 16]> for IPv6 {
144    fn from(octets: [u8; 16]) -> Self {
145        let first = (u64::from(octets[0]) << 56)
146            + (u64::from(octets[1]) << 48)
147            + (u64::from(octets[2]) << 40)
148            + (u64::from(octets[3]) << 32)
149            + (u64::from(octets[4]) << 24)
150            + (u64::from(octets[5]) << 16)
151            + (u64::from(octets[6]) << 8)
152            + u64::from(octets[7]);
153        let last = (u64::from(octets[8]) << 56)
154            + (u64::from(octets[9]) << 48)
155            + (u64::from(octets[10]) << 40)
156            + (u64::from(octets[11]) << 32)
157            + (u64::from(octets[12]) << 24)
158            + (u64::from(octets[13]) << 16)
159            + (u64::from(octets[14]) << 8)
160            + u64::from(octets[15]);
161        Self { first, last }
162    }
163}
164
165impl From<std::net::Ipv6Addr> for IPv6 {
166    #[inline]
167    fn from(v6: std::net::Ipv6Addr) -> Self {
168        Self::from(v6.octets())
169    }
170}
171
172impl From<IPv6> for std::net::Ipv6Addr {
173    fn from(ip: IPv6) -> std::net::Ipv6Addr {
174        std::net::Ipv6Addr::new(
175            (ip.first >> 48) as u16,
176            (ip.first >> 32) as u16,
177            (ip.first >> 16) as u16,
178            (ip.first) as u16,
179            (ip.last >> 48) as u16,
180            (ip.last >> 32) as u16,
181            (ip.last >> 16) as u16,
182            (ip.last) as u16,
183        )
184    }
185}
186
187// === impl TcpAddress ===
188
189impl From<std::net::SocketAddr> for TcpAddress {
190    fn from(sa: std::net::SocketAddr) -> TcpAddress {
191        TcpAddress {
192            ip: Some(sa.ip().into()),
193            port: u32::from(sa.port()),
194        }
195    }
196}
197
198impl TryFrom<TcpAddress> for std::net::SocketAddr {
199    type Error = InvalidIpAddress;
200
201    fn try_from(tcp: TcpAddress) -> Result<std::net::SocketAddr, Self::Error> {
202        if let Some(ip) = tcp.ip {
203            let port = tcp.port as u16;
204            let ip = std::net::IpAddr::try_from(ip)?;
205            return Ok(std::net::SocketAddr::from((ip, port)));
206        }
207
208        Err(InvalidIpAddress)
209    }
210}
211
212#[cfg(feature = "arbitrary")]
213mod arbitary {
214    use super::*;
215    use quickcheck::*;
216
217    impl Arbitrary for IpAddress {
218        fn arbitrary(g: &mut Gen) -> Self {
219            IpAddress {
220                ip: Arbitrary::arbitrary(g),
221            }
222        }
223    }
224
225    impl Arbitrary for ip_address::Ip {
226        fn arbitrary(g: &mut Gen) -> Self {
227            if bool::arbitrary(g) {
228                ip_address::Ip::Ipv4(Arbitrary::arbitrary(g))
229            } else {
230                ip_address::Ip::Ipv6(IPv6::arbitrary(g))
231            }
232        }
233    }
234
235    impl Arbitrary for IPv6 {
236        fn arbitrary(g: &mut Gen) -> Self {
237            IPv6 {
238                first: Arbitrary::arbitrary(g),
239                last: Arbitrary::arbitrary(g),
240            }
241        }
242    }
243}