resolv_conf/
ip.rs

1use std::error::Error;
2use std::fmt;
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4use std::str::FromStr;
5
6/// A network, that is an IP address and a mask
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Network {
9    /// Represent an IPv4 network address
10    V4(Ipv4Addr, Ipv4Addr),
11    /// Represent an IPv6 network address
12    V6(Ipv6Addr, Ipv6Addr),
13}
14
15impl fmt::Display for Network {
16    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
17        match *self {
18            Network::V4(address, mask) => write!(fmt, "{}/{}", address, mask),
19            Network::V6(address, mask) => write!(fmt, "{}/{}", address, mask),
20        }
21    }
22}
23
24/// Represent an IP address. This type is similar to `std::net::IpAddr` but it supports IPv6 scope
25/// identifiers.
26#[derive(Debug, Clone, PartialEq, Eq)]
27pub enum ScopedIp {
28    /// Represent an IPv4 address
29    V4(Ipv4Addr),
30    /// Represent an IPv6 and its scope identifier, if any
31    V6(Ipv6Addr, Option<String>),
32}
33
34impl Into<IpAddr> for ScopedIp {
35    fn into(self) -> IpAddr {
36        match self {
37            ScopedIp::V4(ip) => IpAddr::from(ip),
38            ScopedIp::V6(ip, _) => IpAddr::from(ip),
39        }
40    }
41}
42
43impl<'a> Into<IpAddr> for &'a ScopedIp {
44    fn into(self) -> IpAddr {
45        match *self {
46            ScopedIp::V4(ref ip) => IpAddr::from(*ip),
47            ScopedIp::V6(ref ip, _) => IpAddr::from(*ip),
48        }
49    }
50}
51
52impl From<Ipv6Addr> for ScopedIp {
53    fn from(value: Ipv6Addr) -> Self {
54        ScopedIp::V6(value, None)
55    }
56}
57
58impl From<Ipv4Addr> for ScopedIp {
59    fn from(value: Ipv4Addr) -> Self {
60        ScopedIp::V4(value)
61    }
62}
63
64impl From<IpAddr> for ScopedIp {
65    fn from(value: IpAddr) -> Self {
66        match value {
67            IpAddr::V4(ip) => ScopedIp::from(ip),
68            IpAddr::V6(ip) => ScopedIp::from(ip),
69        }
70    }
71}
72
73impl FromStr for ScopedIp {
74    type Err = AddrParseError;
75    /// Parse a string representing an IP address.
76    fn from_str(s: &str) -> Result<ScopedIp, AddrParseError> {
77        let mut parts = s.split('%');
78        let addr = parts.next().unwrap();
79        match IpAddr::from_str(addr) {
80            Ok(IpAddr::V4(ip)) => {
81                if parts.next().is_some() {
82                    // It's not a valid IPv4 address if it contains a '%'
83                    Err(AddrParseError)
84                } else {
85                    Ok(ScopedIp::from(ip))
86                }
87            }
88            Ok(IpAddr::V6(ip)) => if let Some(scope_id) = parts.next() {
89                if scope_id.is_empty() {
90                    return Err(AddrParseError);
91                }
92                for c in scope_id.chars() {
93                    if !c.is_alphanumeric() {
94                        return Err(AddrParseError);
95                    }
96                }
97                Ok(ScopedIp::V6(ip, Some(scope_id.to_string())))
98            } else {
99                Ok(ScopedIp::V6(ip, None))
100            },
101            Err(e) => Err(e.into()),
102        }
103    }
104}
105
106impl fmt::Display for ScopedIp {
107    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
108        match *self {
109            ScopedIp::V4(ref address) => address.fmt(fmt),
110            ScopedIp::V6(ref address, None) => address.fmt(fmt),
111            ScopedIp::V6(ref address, Some(ref scope)) => write!(fmt, "{}%{}", address, scope),
112        }
113    }
114}
115
116/// An error which can be returned when parsing an IP address.
117#[derive(Debug, Clone, PartialEq, Eq)]
118pub struct AddrParseError;
119
120impl fmt::Display for AddrParseError {
121    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
122        fmt.write_str(self.description())
123    }
124}
125
126impl Error for AddrParseError {
127    fn description(&self) -> &str {
128        "invalid IP address syntax"
129    }
130}
131
132impl From<::std::net::AddrParseError> for AddrParseError {
133    fn from(_: ::std::net::AddrParseError) -> Self {
134        AddrParseError
135    }
136}