1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use default_net::mac::MacAddr;
use netprobe::{neighbor::DeviceResolver, setting::ProbeSetting};
use std::{collections::HashMap, net::IpAddr};
use xenet::net::ipnet::{Ipv4Net, Ipv6Net};

pub fn get_network_address(ip_addr: IpAddr) -> Result<String, String> {
    match ip_addr {
        IpAddr::V4(ipv4_addr) => {
            let net: Ipv4Net = Ipv4Net::new(ipv4_addr, 24);
            Ok(net.network().to_string())
        }
        IpAddr::V6(ipv6_addr) => {
            let net: Ipv6Net = Ipv6Net::new(ipv6_addr, 24);
            Ok(net.network().to_string())
        }
    }
}

pub fn is_global_addr(ip_addr: IpAddr) -> bool {
    match ip_addr {
        IpAddr::V4(ipv4) => xenet::net::ipnet::is_global_ipv4(&ipv4),
        IpAddr::V6(ipv6) => xenet::net::ipnet::is_global_ipv6(&ipv6),
    }
}

pub fn in_same_network(src_ip: IpAddr, dst_ip: IpAddr) -> bool {
    let src_ip_nw = match get_network_address(src_ip) {
        Ok(nw) => nw,
        Err(_) => return false,
    };
    let dst_ip_nw = match get_network_address(dst_ip) {
        Ok(nw) => nw,
        Err(_) => return false,
    };
    if src_ip_nw == dst_ip_nw {
        true
    } else {
        false
    }
}

pub fn guess_initial_ttl(ttl: u8) -> u8 {
    if ttl <= 64 {
        64
    } else if 64 < ttl && ttl <= 128 {
        128
    } else {
        255
    }
}

pub fn get_mac_addresses(ips: Vec<IpAddr>, src_ip: IpAddr) -> HashMap<IpAddr, String> {
    let mut map: HashMap<IpAddr, String> = HashMap::new();
    if let Some(c_interface) = crate::interface::get_interface_by_ip(src_ip) {
        for ip in ips {
            if ip == src_ip {
                map.insert(
                    ip,
                    c_interface
                        .clone()
                        .mac_addr
                        .unwrap_or(MacAddr::zero())
                        .to_string(),
                );
                continue;
            }
            if !is_global_addr(ip) && in_same_network(src_ip, ip) {
                let setting: ProbeSetting = match ip {
                    IpAddr::V4(ipv4) => ProbeSetting::arp(c_interface.clone(), ipv4, 1).unwrap(),
                    IpAddr::V6(ipv6) => ProbeSetting::ndp(c_interface.clone(), ipv6, 1).unwrap(),
                };
                let resolver: DeviceResolver = DeviceResolver::new(setting).unwrap();
                match resolver.resolve() {
                    Ok(result) => {
                        if result.results.len() > 0 {
                            map.insert(ip, result.results[0].mac_addr.address());
                        }
                    }
                    Err(_) => {}
                }
            }
        }
    }
    map
}