network_interface/utils/
unix.rs

1use std::net::{Ipv4Addr, Ipv6Addr};
2use libc::{in6_addr, in_addr, sockaddr_in, sockaddr_in6};
3
4use crate::Result;
5use crate::interface::Netmask;
6
7/// Creates a `Ipv4Addr` from a (Unix) `in_addr` taking in account
8/// the CPU endianess to avoid having twisted IP addresses.
9///
10/// refer: https://github.com/rust-lang/rust/issues/48819
11pub fn ipv4_from_in_addr(internet_address: &in_addr) -> Result<Ipv4Addr> {
12    let mut ip_addr = Ipv4Addr::from(internet_address.s_addr);
13
14    if cfg!(target_endian = "little") {
15        // due to a difference on how bytes are arranged on a
16        // single word of memory by the CPU, swap bytes based
17        // on CPU endianess to avoid having twisted IP addresses
18        ip_addr = Ipv4Addr::from(internet_address.s_addr.swap_bytes());
19    }
20
21    Ok(ip_addr)
22}
23
24/// Creates a `Ipv6Addr` from a (Unix) `in6_addr`
25pub fn ipv6_from_in6_addr(internet_address: &in6_addr) -> Result<Ipv6Addr> {
26    let ip_addr = Ipv6Addr::from(internet_address.s6_addr);
27
28    Ok(ip_addr)
29}
30
31/// Retrieves the Netmask from a `ifaddrs` instance for a network interface
32/// from the AF_INET (IPv4) family.
33pub fn make_ipv4_netmask(netifa: &libc::ifaddrs) -> Netmask<Ipv4Addr> {
34    let sockaddr = netifa.ifa_netmask;
35
36    if sockaddr.is_null() {
37        return None;
38    }
39
40    let socket_addr = sockaddr as *mut sockaddr_in;
41    let internet_address = unsafe { (*socket_addr).sin_addr };
42
43    ipv4_from_in_addr(&internet_address).ok()
44}
45
46/// Retrieves the Netmask from a `ifaddrs` instance for a network interface
47/// from the AF_INET6 (IPv6) family.
48pub fn make_ipv6_netmask(netifa: &libc::ifaddrs) -> Netmask<Ipv6Addr> {
49    let sockaddr = netifa.ifa_netmask;
50
51    if sockaddr.is_null() {
52        return None;
53    }
54
55    let socket_addr = sockaddr as *mut sockaddr_in6;
56    let internet_address = unsafe { (*socket_addr).sin6_addr };
57
58    //  Ignore local addresses
59    if internet_address.s6_addr[0] == 0xfe && internet_address.s6_addr[1] == 0x80 {
60        return None;
61    }
62
63    ipv6_from_in6_addr(&internet_address).ok()
64}