zond_engine/system/interface/
utils.rs1use crate::core::models::ip::set::IpSet;
8use pnet::datalink::NetworkInterface;
9
10pub fn get_prioritized_interfaces(limit: usize) -> anyhow::Result<Vec<NetworkInterface>> {
14 let interfaces: Vec<NetworkInterface> = pnet::datalink::interfaces()
15 .into_iter()
16 .filter(|i| i.is_up() && !i.is_loopback() && !i.ips.is_empty())
17 .collect();
18
19 Ok(get_prioritized_interfaces_with(limit, interfaces))
20}
21
22pub(crate) fn get_prioritized_interfaces_with(
24 limit: usize,
25 mut interfaces: Vec<NetworkInterface>,
26) -> Vec<NetworkInterface> {
27 interfaces.sort_by_key(|i| if i.name.starts_with("e") { 0 } else { 1 });
28 interfaces.into_iter().take(limit).collect()
29}
30
31pub fn is_layer_2_capable(intf: &NetworkInterface) -> bool {
35 !intf.is_point_to_point() && !intf.is_loopback() && intf.mac.is_some()
36}
37
38pub fn is_on_link(intf: &NetworkInterface, ips: &mut IpSet) -> bool {
40 for range in ips.v4() {
41 let mut range_covered = false;
42 for iface_ipnet in &intf.ips {
43 if let pnet::ipnetwork::IpNetwork::V4(network) = iface_ipnet
44 && network.contains(range.start_addr)
45 && network.contains(range.end_addr)
46 {
47 range_covered = true;
48 break;
49 }
50 }
51 if !range_covered {
52 return false;
53 }
54 }
55 true
56}
57
58#[cfg(test)]
68mod tests {
69 use super::*;
70 use pnet::datalink::MacAddr;
71
72 fn mock_interface(name: &str, p2p: bool, loopback: bool, mac: bool) -> NetworkInterface {
73 NetworkInterface {
74 name: name.to_string(),
75 description: "".to_string(),
76 index: 0,
77 mac: if mac {
78 Some(MacAddr::new(1, 2, 3, 4, 5, 6))
79 } else {
80 None
81 },
82 ips: vec![],
83 flags: {
84 let mut flags = 0;
85 if p2p {
86 flags |= 16;
87 }
88 if loopback {
89 flags |= 8;
90 }
91 flags
92 },
93 }
94 }
95
96 #[test]
97 fn test_is_layer_2_capable() {
98 assert!(is_layer_2_capable(&mock_interface(
99 "eth0", false, false, true
100 )));
101 assert!(!is_layer_2_capable(&mock_interface(
102 "eth0", true, false, true
103 )));
104 assert!(!is_layer_2_capable(&mock_interface(
105 "eth0", false, true, true
106 )));
107 assert!(!is_layer_2_capable(&mock_interface(
108 "eth0", false, false, false
109 )));
110 }
111
112 #[test]
113 fn test_sorting_prioritizes_eth_interfaces() {
114 let interfaces = vec![
115 mock_interface("wlan0", false, false, true),
116 mock_interface("eth0", false, false, true),
117 ];
118
119 let sorted = get_prioritized_interfaces_with(10, interfaces);
120 assert_eq!(sorted[0].name, "eth0");
121 assert_eq!(sorted[1].name, "wlan0");
122 }
123}