default_net/
ip.rs

1use core::fmt;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7/// Structure of IP Network
8#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
9#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10pub enum IpNet {
11    V4(Ipv4Net),
12    V6(Ipv6Net),
13}
14
15impl IpNet {
16    /// Construct a new IpNet instance from IP Address and Prefix Length
17    pub fn new(ip: IpAddr, prefix_len: u8) -> IpNet {
18        match ip {
19            IpAddr::V4(addr) => Ipv4Net::new(addr, prefix_len).into(),
20            IpAddr::V6(addr) => Ipv6Net::new(addr, prefix_len).into(),
21        }
22    }
23    /// Construct a new IpNet instance from IP Address and Network Mask
24    pub fn new_with_netmask(ip: IpAddr, netmask: IpAddr) -> IpNet {
25        let prefix = ip_netmask_to_prefix(netmask);
26        Self::new(ip, prefix)
27    }
28    /// Returns the address.
29    pub fn addr(&self) -> IpAddr {
30        match *self {
31            IpNet::V4(ref a) => IpAddr::V4(a.addr),
32            IpNet::V6(ref a) => IpAddr::V6(a.addr),
33        }
34    }
35    /// Returns the prefix length.
36    pub fn prefix_len(&self) -> u8 {
37        match *self {
38            IpNet::V4(ref a) => a.prefix_len,
39            IpNet::V6(ref a) => a.prefix_len,
40        }
41    }
42    /// Returns the maximum valid prefix length.
43    pub fn max_prefix_len(&self) -> u8 {
44        match *self {
45            IpNet::V4(ref a) => a.max_prefix_len(),
46            IpNet::V6(ref a) => a.max_prefix_len(),
47        }
48    }
49    /// Returns the network mask.
50    pub fn netmask(&self) -> IpAddr {
51        match *self {
52            IpNet::V4(ref a) => IpAddr::V4(a.netmask()),
53            IpNet::V6(ref a) => IpAddr::V6(a.netmask()),
54        }
55    }
56    /// Returns the host mask.
57    pub fn hostmask(&self) -> IpAddr {
58        match *self {
59            IpNet::V4(ref a) => IpAddr::V4(a.hostmask()),
60            IpNet::V6(ref a) => IpAddr::V6(a.hostmask()),
61        }
62    }
63    /// Returns the network address.
64    pub fn network(&self) -> IpAddr {
65        match *self {
66            IpNet::V4(ref a) => IpAddr::V4(a.network()),
67            IpNet::V6(ref a) => IpAddr::V6(a.network()),
68        }
69    }
70    /// Returns the broadcast address.
71    pub fn broadcast(&self) -> IpAddr {
72        match *self {
73            IpNet::V4(ref a) => IpAddr::V4(a.broadcast()),
74            IpNet::V6(ref a) => IpAddr::V6(a.broadcast()),
75        }
76    }
77}
78
79impl From<Ipv4Net> for IpNet {
80    fn from(net: Ipv4Net) -> IpNet {
81        IpNet::V4(net)
82    }
83}
84
85impl From<Ipv6Net> for IpNet {
86    fn from(net: Ipv6Net) -> IpNet {
87        IpNet::V6(net)
88    }
89}
90
91impl From<IpAddr> for IpNet {
92    fn from(addr: IpAddr) -> IpNet {
93        match addr {
94            IpAddr::V4(addr) => IpNet::V4(addr.into()),
95            IpAddr::V6(addr) => IpNet::V6(addr.into()),
96        }
97    }
98}
99
100/// Structure of IPv4 Network
101#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103pub struct Ipv4Net {
104    /// IPv4 Address
105    pub addr: Ipv4Addr,
106    /// Prefix Length
107    pub prefix_len: u8,
108    /// Network Mask
109    pub netmask: Ipv4Addr,
110}
111
112impl Ipv4Net {
113    /// Construct a new Ipv4Net instance from IPv4 Address and Prefix Length
114    pub fn new(ipv4_addr: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
115        Ipv4Net {
116            addr: ipv4_addr,
117            prefix_len: prefix_len,
118            netmask: prefix_to_ipv4_netmask(prefix_len),
119        }
120    }
121    /// Construct a new Ipv4Net instance from IPv4 Address and Network Mask
122    pub fn new_with_netmask(ipv4_addr: Ipv4Addr, netmask: Ipv4Addr) -> Ipv4Net {
123        Ipv4Net {
124            addr: ipv4_addr,
125            prefix_len: ipv4_netmask_to_prefix(netmask),
126            netmask: netmask,
127        }
128    }
129    /// Returns the maximum valid prefix length.
130    pub const fn max_prefix_len(&self) -> u8 {
131        32
132    }
133    /// Returns the network mask.
134    pub fn netmask(&self) -> Ipv4Addr {
135        Ipv4Addr::from(self.netmask_u32())
136    }
137    /// Returns the network mask. (u32)
138    fn netmask_u32(&self) -> u32 {
139        u32::max_value()
140            .checked_shl(32 - self.prefix_len as u32)
141            .unwrap_or(0)
142    }
143    /// Returns the host mask.
144    pub fn hostmask(&self) -> Ipv4Addr {
145        Ipv4Addr::from(self.hostmask_u32())
146    }
147    /// Returns the host mask. (u32)
148    fn hostmask_u32(&self) -> u32 {
149        u32::max_value()
150            .checked_shr(self.prefix_len as u32)
151            .unwrap_or(0)
152    }
153    /// Returns the network address.
154    pub fn network(&self) -> Ipv4Addr {
155        Ipv4Addr::from(u32::from(self.addr) & self.netmask_u32())
156    }
157    /// Returns the broadcast address.
158    pub fn broadcast(&self) -> Ipv4Addr {
159        Ipv4Addr::from(u32::from(self.addr) | self.hostmask_u32())
160    }
161}
162
163impl fmt::Debug for Ipv4Net {
164    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
165        fmt::Display::fmt(self, fmt)
166    }
167}
168
169impl fmt::Display for Ipv4Net {
170    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
171        write!(fmt, "{}/{}", self.addr, self.prefix_len)
172    }
173}
174
175impl From<Ipv4Addr> for Ipv4Net {
176    fn from(addr: Ipv4Addr) -> Ipv4Net {
177        Ipv4Net {
178            addr,
179            prefix_len: 32,
180            netmask: prefix_to_ipv4_netmask(32),
181        }
182    }
183}
184
185/// Structure of IPv6 Network
186#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
187#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
188pub struct Ipv6Net {
189    /// IPv6 Address
190    pub addr: Ipv6Addr,
191    /// Prefix Length
192    pub prefix_len: u8,
193    /// Network Mask
194    pub netmask: Ipv6Addr,
195}
196
197impl Ipv6Net {
198    /// Construct a new Ipv6Net instance from IPv6 Address and Prefix Length
199    pub fn new(ipv6_addr: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
200        Ipv6Net {
201            addr: ipv6_addr,
202            prefix_len: prefix_len,
203            netmask: prefix_to_ipv6_netmask(prefix_len),
204        }
205    }
206    /// Construct a new Ipv6Net instance from IPv6 Address and Network Mask
207    pub fn new_with_netmask(ipv6_addr: Ipv6Addr, netmask: Ipv6Addr) -> Ipv6Net {
208        Ipv6Net {
209            addr: ipv6_addr,
210            prefix_len: ipv6_netmask_to_prefix(netmask),
211            netmask: netmask,
212        }
213    }
214    /// Returns the maximum valid prefix length.
215    pub const fn max_prefix_len(&self) -> u8 {
216        128
217    }
218    /// Returns the network mask.
219    pub fn netmask(&self) -> Ipv6Addr {
220        self.netmask_u128().into()
221    }
222    /// Returns the network mask. (u128)
223    fn netmask_u128(&self) -> u128 {
224        u128::max_value()
225            .checked_shl((128 - self.prefix_len) as u32)
226            .unwrap_or(u128::min_value())
227    }
228    /// Returns the host mask.
229    pub fn hostmask(&self) -> Ipv6Addr {
230        self.hostmask_u128().into()
231    }
232    /// Returns the host mask. (u128)
233    fn hostmask_u128(&self) -> u128 {
234        u128::max_value()
235            .checked_shr(self.prefix_len as u32)
236            .unwrap_or(u128::min_value())
237    }
238    /// Returns the network address.
239    pub fn network(&self) -> Ipv6Addr {
240        (u128::from(self.addr) & self.netmask_u128()).into()
241    }
242    /// Returns the broadcast address.
243    pub fn broadcast(&self) -> Ipv6Addr {
244        (u128::from(self.addr) | self.hostmask_u128()).into()
245    }
246}
247
248impl fmt::Debug for Ipv6Net {
249    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
250        fmt::Display::fmt(self, fmt)
251    }
252}
253
254impl fmt::Display for Ipv6Net {
255    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
256        write!(fmt, "{}/{}", self.addr, self.prefix_len)
257    }
258}
259
260impl From<Ipv6Addr> for Ipv6Net {
261    fn from(addr: Ipv6Addr) -> Ipv6Net {
262        Ipv6Net {
263            addr,
264            prefix_len: 128,
265            netmask: prefix_to_ipv6_netmask(128),
266        }
267    }
268}
269
270fn ip_netmask_to_prefix(mask: IpAddr) -> u8 {
271    match mask {
272        IpAddr::V4(mask) => ipv4_netmask_to_prefix(mask),
273        IpAddr::V6(mask) => ipv6_netmask_to_prefix(mask),
274    }
275}
276
277fn ipv4_netmask_to_prefix(netmask: Ipv4Addr) -> u8 {
278    let netmask = u32::from(netmask);
279    let prefix = (!netmask).leading_zeros() as u8;
280    if (u64::from(netmask) << prefix) & 0xffff_ffff != 0 {
281        0
282    } else {
283        prefix
284    }
285}
286
287fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 {
288    let netmask = netmask.segments();
289    let mut mask_iter = netmask.iter();
290    let mut prefix = 0;
291    for &segment in &mut mask_iter {
292        if segment == 0xffff {
293            prefix += 16;
294        } else if segment == 0 {
295            break;
296        } else {
297            let prefix_bits = (!segment).leading_zeros() as u8;
298            if segment << prefix_bits != 0 {
299                return 0;
300            }
301            prefix += prefix_bits;
302            break;
303        }
304    }
305    for &segment in mask_iter {
306        if segment != 0 {
307            return 0;
308        }
309    }
310    prefix
311}
312
313fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr {
314    let netmask_u32: u32 = u32::max_value()
315        .checked_shl(32 - prefix_len as u32)
316        .unwrap_or(0);
317    Ipv4Addr::from(netmask_u32)
318}
319
320fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr {
321    let netmask_u128: u128 = u128::max_value()
322        .checked_shl((128 - prefix_len) as u32)
323        .unwrap_or(u128::min_value());
324    Ipv6Addr::from(netmask_u128)
325}