reth_net_nat/
net_if.rs

1//! IP resolution on non-host Docker network.
2
3use std::{io, net::IpAddr};
4
5/// The 'eth0' interface tends to be the default interface that docker containers use to
6/// communicate with each other.
7pub const DEFAULT_NET_IF_NAME: &str = "eth0";
8
9/// Errors resolving network interface IP.
10#[derive(Debug, thiserror::Error)]
11pub enum NetInterfaceError {
12    /// Error reading OS interfaces.
13    #[error("failed to read OS interfaces: {0}")]
14    Io(io::Error),
15    /// No interface found with given name.
16    #[error("interface not found: {0}, found other interfaces: {1:?}")]
17    IFNotFound(String, Vec<String>),
18}
19
20/// Reads IP of OS interface with given name, if exists.
21pub fn resolve_net_if_ip(if_name: &str) -> Result<IpAddr, NetInterfaceError> {
22    match if_addrs::get_if_addrs() {
23        Ok(ifs) => {
24            let ip = ifs.iter().find(|i| i.name == if_name).map(|i| i.ip());
25            match ip {
26                Some(ip) => Ok(ip),
27                None => {
28                    let ifs = ifs.into_iter().map(|i| i.name.as_str().into()).collect();
29                    Err(NetInterfaceError::IFNotFound(if_name.into(), ifs))
30                }
31            }
32        }
33        Err(err) => Err(NetInterfaceError::Io(err)),
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use std::net::Ipv4Addr;
41
42    #[test]
43    fn read_docker_if_addr() {
44        const LOCALHOST_IF: [&str; 2] = ["lo0", "lo"];
45
46        let ip = resolve_net_if_ip(LOCALHOST_IF[0])
47            .unwrap_or_else(|_| resolve_net_if_ip(LOCALHOST_IF[1]).unwrap());
48
49        assert_eq!(ip, Ipv4Addr::LOCALHOST);
50    }
51}