e_libscanner/interface/
mod.rs

1use std::convert::TryFrom;
2use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket};
3#[cfg(target_os = "windows")]
4#[path = "./windows.rs"]
5mod win;
6#[cfg(target_os = "windows")]
7use win::get_interfaces;
8#[cfg(any(target_os = "unix", target_os = "linux"))]
9mod unix;
10#[cfg(any(target_os = "unix", target_os = "linux"))]
11use unix::get_interfaces;
12
13mod memalloc;
14/// Structure of Network Interface information
15#[derive(Clone, Debug)]
16pub struct Interface {
17    /// Index of network interface
18    pub index: u32,
19    /// Name of network interface
20    pub name: String,
21    /// Friendly Name of network interface
22    pub friendly_name: Option<String>,
23    /// Description of the network interface
24    pub description: Option<String>,
25    /// Interface Type
26    pub if_type: InterfaceType,
27    /// MAC address of network interface
28    pub mac_addr: Option<MacAddr>,
29    /// List of Ipv4Net for the network interface
30    pub ipv4: Vec<Ipv4Net>,
31    /// List of Ipv6Net for the network interface
32    pub ipv6: Vec<Ipv6Net>,
33    /// Flags for the network interface (OS Specific)
34    pub flags: u32,
35    /// Speed in bits per second of the transmit for the network interface
36    pub transmit_speed: Option<u64>,
37    /// Speed in bits per second of the receive for the network interface
38    pub receive_speed: Option<u64>,
39    /// Default gateway for the network interface
40    pub gateway: Option<Gateway>,
41}
42
43/// Structure of default Gateway information
44#[derive(Clone, Debug)]
45pub struct Gateway {
46    /// MAC address of Gateway
47    pub mac_addr: MacAddr,
48    /// IP address of Gateway
49    pub ip_addr: IpAddr,
50}
51
52impl Gateway {
53    /// Construct a new Gateway instance
54    pub fn new() -> Gateway {
55        Gateway {
56            mac_addr: MacAddr::zero(),
57            ip_addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
58        }
59    }
60}
61/// Get default Gateway
62pub fn get_default_gateway() -> Result<Gateway, String> {
63    let local_ip: IpAddr = match get_local_ipaddr() {
64        Ok(local_ip) => local_ip,
65        Err(_) => return Err(String::from("Local IP address not found")),
66    };
67    let interfaces: Vec<Interface> = get_interfaces();
68    for iface in interfaces {
69        match local_ip {
70            IpAddr::V4(local_ipv4) => {
71                if iface.ipv4.iter().any(|x| x.addr == local_ipv4) {
72                    if let Some(gateway) = iface.gateway {
73                        return Ok(gateway);
74                    }
75                }
76            }
77            IpAddr::V6(local_ipv6) => {
78                if iface.ipv6.iter().any(|x| x.addr == local_ipv6) {
79                    if let Some(gateway) = iface.gateway {
80                        return Ok(gateway);
81                    }
82                }
83            }
84        }
85    }
86    Err(String::from("Default Gateway not found"))
87}
88
89/// Get IP address of the default Network Interface
90pub fn get_local_ipaddr() -> Result<IpAddr, String> {
91    let socket = match UdpSocket::bind("0.0.0.0:0") {
92        Ok(s) => s,
93        Err(e) => return Err(String::from(e.to_string())),
94    };
95    if let Err(e) = socket.connect("1.1.1.1:80") {
96        return Err(String::from(e.to_string()));
97    };
98    match socket.local_addr() {
99        Ok(addr) => Ok(addr.ip()),
100        Err(e) => return Err(String::from(e.to_string())),
101    }
102}
103
104/// Get interface index by ip
105pub fn get_interface_index_by_ip(ip_addr: IpAddr) -> Option<u32> {
106    for iface in pnet_datalink::interfaces() {
107        for ip in iface.ips {
108            if ip.ip() == ip_addr {
109                return Some(iface.index);
110            }
111        }
112    }
113    return None;
114}
115
116/// Get default gateway mac address on windows
117#[cfg(target_os = "windows")]
118pub fn get_default_gateway_macaddr() -> [u8; 6] {
119    match get_default_gateway() {
120        Ok(gateway) => gateway.mac_addr.octets(),
121        Err(_) => MacAddr::zero().octets(),
122    }
123}
124
125/// Get default gateway mac address on not windows
126#[cfg(not(target_os = "windows"))]
127pub fn get_default_gateway_macaddr() -> [u8; 6] {
128    MacAddr::zero().octets()
129}
130
131/// Type of Network Interface
132#[derive(Clone, Copy, Debug, PartialEq)]
133pub enum InterfaceType {
134    /// Unknown interface type
135    Unknown,
136    /// The network interface using an Ethernet connection
137    Ethernet,
138    /// The network interface using a Token-Ring connection
139    TokenRing,
140    /// The network interface using a Fiber Distributed Data Interface (FDDI) connection
141    Fddi,
142    /// The network interface using a basic rate interface Integrated Services Digital Network (ISDN) connection
143    BasicIsdn,
144    /// The network interface using a primary rate interface Integrated Services Digital Network (ISDN) connection
145    PrimaryIsdn,
146    /// The network interface using a Point-To-Point protocol (PPP) connection
147    Ppp,
148    /// The loopback interface (often used for testing)
149    Loopback,
150    /// The network interface using an Ethernet 3 megabit/second connection
151    Ethernet3Megabit,
152    /// The network interface using a Serial Line Internet Protocol (SLIP) connection
153    Slip,
154    /// The network interface using asynchronous transfer mode (ATM) for data transmission
155    Atm,
156    /// The network interface using a modem
157    GenericModem,
158    /// The network interface using a Fast Ethernet connection over twisted pair and provides a data rate of 100 megabits per second (100BASE-T)
159    FastEthernetT,
160    /// The network interface using a connection configured for ISDN and the X.25 protocol.
161    Isdn,
162    /// The network interface using a Fast Ethernet connection over optical fiber and provides a data rate of 100 megabits per second (100Base-FX)
163    FastEthernetFx,
164    /// The network interface using a wireless LAN connection (IEEE 802.11)
165    Wireless80211,
166    /// The network interface using an Asymmetric Digital Subscriber Line (ADSL)
167    AsymmetricDsl,
168    /// The network interface using a Rate Adaptive Digital Subscriber Line (RADSL)
169    RateAdaptDsl,
170    /// The network interface using a Symmetric Digital Subscriber Line (SDSL)
171    SymmetricDsl,
172    /// The network interface using a Very High Data Rate Digital Subscriber Line (VDSL)
173    VeryHighSpeedDsl,
174    /// The network interface using the Internet Protocol (IP) in combination with asynchronous transfer mode (ATM) for data transmission
175    IPOverAtm,
176    /// The network interface using a gigabit Ethernet connection and provides a data rate of 1,000 megabits per second (1 gigabit per second)
177    GigabitEthernet,
178    /// The network interface using a tunnel connection
179    Tunnel,
180    /// The network interface using a Multirate Digital Subscriber Line
181    MultiRateSymmetricDsl,
182    /// The network interface using a High Performance Serial Bus
183    HighPerformanceSerialBus,
184    /// The network interface using a mobile broadband interface for WiMax devices
185    Wman,
186    /// The network interface using a mobile broadband interface for GSM-based devices
187    Wwanpp,
188    /// The network interface using a mobile broadband interface for CDMA-based devices
189    Wwanpp2,
190}
191
192impl InterfaceType {
193    /// Returns OS-specific value of InterfaceType
194    #[cfg(target_os = "windows")]
195    pub fn value(&self) -> u32 {
196        match *self {
197            InterfaceType::Unknown => 1,
198            InterfaceType::Ethernet => 6,
199            InterfaceType::TokenRing => 9,
200            InterfaceType::Fddi => 15,
201            InterfaceType::BasicIsdn => 20,
202            InterfaceType::PrimaryIsdn => 21,
203            InterfaceType::Ppp => 23,
204            InterfaceType::Loopback => 24,
205            InterfaceType::Ethernet3Megabit => 26,
206            InterfaceType::Slip => 28,
207            InterfaceType::Atm => 37,
208            InterfaceType::GenericModem => 48,
209            InterfaceType::FastEthernetT => 62,
210            InterfaceType::Isdn => 63,
211            InterfaceType::FastEthernetFx => 69,
212            InterfaceType::Wireless80211 => 71,
213            InterfaceType::AsymmetricDsl => 94,
214            InterfaceType::RateAdaptDsl => 95,
215            InterfaceType::SymmetricDsl => 96,
216            InterfaceType::VeryHighSpeedDsl => 97,
217            InterfaceType::IPOverAtm => 114,
218            InterfaceType::GigabitEthernet => 117,
219            InterfaceType::Tunnel => 131,
220            InterfaceType::MultiRateSymmetricDsl => 143,
221            InterfaceType::HighPerformanceSerialBus => 144,
222            InterfaceType::Wman => 237,
223            InterfaceType::Wwanpp => 243,
224            InterfaceType::Wwanpp2 => 244,
225        }
226    }
227    /// Returns OS-specific value of InterfaceType
228    #[cfg(any(target_os = "linux", target_os = "android"))]
229    pub fn value(&self) -> u32 {
230        match *self {
231            InterfaceType::Ethernet => 1,
232            InterfaceType::TokenRing => 4,
233            InterfaceType::Fddi => 774,
234            InterfaceType::Ppp => 512,
235            InterfaceType::Loopback => 772,
236            InterfaceType::Ethernet3Megabit => 2,
237            InterfaceType::Slip => 256,
238            InterfaceType::Atm => 19,
239            InterfaceType::Wireless80211 => 801,
240            InterfaceType::Tunnel => 768,
241            _ => u32::MAX,
242        }
243    }
244    /// Returns OS-specific value of InterfaceType
245    #[cfg(any(
246        target_os = "macos",
247        target_os = "openbsd",
248        target_os = "freebsd",
249        target_os = "netbsd",
250        target_os = "ios"
251    ))]
252    pub fn value(&self) -> u32 {
253        // TODO
254        match *self {
255            _ => 0,
256        }
257    }
258    /// Returns name of InterfaceType
259    pub fn name(&self) -> String {
260        match *self {
261            InterfaceType::Unknown => String::from("Unknown"),
262            InterfaceType::Ethernet => String::from("Ethernet"),
263            InterfaceType::TokenRing => String::from("Token Ring"),
264            InterfaceType::Fddi => String::from("FDDI"),
265            InterfaceType::BasicIsdn => String::from("Basic ISDN"),
266            InterfaceType::PrimaryIsdn => String::from("Primary ISDN"),
267            InterfaceType::Ppp => String::from("PPP"),
268            InterfaceType::Loopback => String::from("Loopback"),
269            InterfaceType::Ethernet3Megabit => String::from("Ethernet 3 megabit"),
270            InterfaceType::Slip => String::from("SLIP"),
271            InterfaceType::Atm => String::from("ATM"),
272            InterfaceType::GenericModem => String::from("Generic Modem"),
273            InterfaceType::FastEthernetT => String::from("Fast Ethernet T"),
274            InterfaceType::Isdn => String::from("ISDN"),
275            InterfaceType::FastEthernetFx => String::from("Fast Ethernet FX"),
276            InterfaceType::Wireless80211 => String::from("Wireless IEEE 802.11"),
277            InterfaceType::AsymmetricDsl => String::from("Asymmetric DSL"),
278            InterfaceType::RateAdaptDsl => String::from("Rate Adaptive DSL"),
279            InterfaceType::SymmetricDsl => String::from("Symmetric DSL"),
280            InterfaceType::VeryHighSpeedDsl => String::from("Very High Data Rate DSL"),
281            InterfaceType::IPOverAtm => String::from("IP over ATM"),
282            InterfaceType::GigabitEthernet => String::from("Gigabit Ethernet"),
283            InterfaceType::Tunnel => String::from("Tunnel"),
284            InterfaceType::MultiRateSymmetricDsl => String::from("Multi-Rate Symmetric DSL"),
285            InterfaceType::HighPerformanceSerialBus => String::from("High Performance Serial Bus"),
286            InterfaceType::Wman => String::from("WMAN"),
287            InterfaceType::Wwanpp => String::from("WWANPP"),
288            InterfaceType::Wwanpp2 => String::from("WWANPP2"),
289        }
290    }
291}
292
293impl TryFrom<u32> for InterfaceType {
294    type Error = ();
295    fn try_from(v: u32) -> Result<Self, Self::Error> {
296        match v {
297            x if x == InterfaceType::Unknown.value() => Ok(InterfaceType::Unknown),
298            x if x == InterfaceType::Ethernet.value() => Ok(InterfaceType::Ethernet),
299            x if x == InterfaceType::TokenRing.value() => Ok(InterfaceType::TokenRing),
300            x if x == InterfaceType::Fddi.value() => Ok(InterfaceType::Fddi),
301            x if x == InterfaceType::BasicIsdn.value() => Ok(InterfaceType::BasicIsdn),
302            x if x == InterfaceType::PrimaryIsdn.value() => Ok(InterfaceType::PrimaryIsdn),
303            x if x == InterfaceType::Ppp.value() => Ok(InterfaceType::Ppp),
304            x if x == InterfaceType::Loopback.value() => Ok(InterfaceType::Loopback),
305            x if x == InterfaceType::Ethernet3Megabit.value() => {
306                Ok(InterfaceType::Ethernet3Megabit)
307            }
308            x if x == InterfaceType::Slip.value() => Ok(InterfaceType::Slip),
309            x if x == InterfaceType::Atm.value() => Ok(InterfaceType::Atm),
310            x if x == InterfaceType::GenericModem.value() => Ok(InterfaceType::GenericModem),
311            x if x == InterfaceType::FastEthernetT.value() => Ok(InterfaceType::FastEthernetT),
312            x if x == InterfaceType::Isdn.value() => Ok(InterfaceType::Isdn),
313            x if x == InterfaceType::FastEthernetFx.value() => Ok(InterfaceType::FastEthernetFx),
314            x if x == InterfaceType::Wireless80211.value() => Ok(InterfaceType::Wireless80211),
315            x if x == InterfaceType::AsymmetricDsl.value() => Ok(InterfaceType::AsymmetricDsl),
316            x if x == InterfaceType::RateAdaptDsl.value() => Ok(InterfaceType::RateAdaptDsl),
317            x if x == InterfaceType::SymmetricDsl.value() => Ok(InterfaceType::SymmetricDsl),
318            x if x == InterfaceType::VeryHighSpeedDsl.value() => {
319                Ok(InterfaceType::VeryHighSpeedDsl)
320            }
321            x if x == InterfaceType::IPOverAtm.value() => Ok(InterfaceType::IPOverAtm),
322            x if x == InterfaceType::GigabitEthernet.value() => Ok(InterfaceType::GigabitEthernet),
323            x if x == InterfaceType::Tunnel.value() => Ok(InterfaceType::Tunnel),
324            x if x == InterfaceType::MultiRateSymmetricDsl.value() => {
325                Ok(InterfaceType::MultiRateSymmetricDsl)
326            }
327            x if x == InterfaceType::HighPerformanceSerialBus.value() => {
328                Ok(InterfaceType::HighPerformanceSerialBus)
329            }
330            x if x == InterfaceType::Wman.value() => Ok(InterfaceType::Wman),
331            x if x == InterfaceType::Wwanpp.value() => Ok(InterfaceType::Wwanpp),
332            x if x == InterfaceType::Wwanpp2.value() => Ok(InterfaceType::Wwanpp2),
333            _ => Err(()),
334        }
335    }
336}
337
338/// Structure of IPv4 Network
339#[derive(Clone, Debug)]
340pub struct Ipv4Net {
341    /// IPv4 Address
342    pub addr: Ipv4Addr,
343    /// Prefix Length
344    pub prefix_len: u8,
345    /// Network Mask
346    pub netmask: Ipv4Addr,
347}
348
349impl Ipv4Net {
350    /// Construct a new Ipv4Net instance from IPv4 Address and Prefix Length
351    pub fn new(ipv4_addr: Ipv4Addr, prefix_len: u8) -> Ipv4Net {
352        Ipv4Net {
353            addr: ipv4_addr,
354            prefix_len: prefix_len,
355            netmask: prefix_to_ipv4_netmask(prefix_len),
356        }
357    }
358    /// Construct a new Ipv4Net instance from IPv4 Address and Network Mask
359    pub fn new_with_netmask(ipv4_addr: Ipv4Addr, netmask: Ipv4Addr) -> Ipv4Net {
360        Ipv4Net {
361            addr: ipv4_addr,
362            prefix_len: ipv4_netmask_to_prefix(netmask),
363            netmask: netmask,
364        }
365    }
366}
367
368/// Structure of IPv6 Network
369#[derive(Clone, Debug)]
370pub struct Ipv6Net {
371    /// IPv6 Address
372    pub addr: Ipv6Addr,
373    /// Prefix Length
374    pub prefix_len: u8,
375    /// Network Mask
376    pub netmask: Ipv6Addr,
377}
378
379impl Ipv6Net {
380    /// Construct a new Ipv6Net instance from IPv6 Address and Prefix Length
381    pub fn new(ipv6_addr: Ipv6Addr, prefix_len: u8) -> Ipv6Net {
382        Ipv6Net {
383            addr: ipv6_addr,
384            prefix_len: prefix_len,
385            netmask: prefix_to_ipv6_netmask(prefix_len),
386        }
387    }
388    /// Construct a new Ipv6Net instance from IPv6 Address and Network Mask
389    pub fn new_with_netmask(ipv6_addr: Ipv6Addr, netmask: Ipv6Addr) -> Ipv6Net {
390        Ipv6Net {
391            addr: ipv6_addr,
392            prefix_len: ipv6_netmask_to_prefix(netmask),
393            netmask: netmask,
394        }
395    }
396}
397
398fn ipv4_netmask_to_prefix(netmask: Ipv4Addr) -> u8 {
399    let netmask = u32::from(netmask);
400    let prefix = (!netmask).leading_zeros() as u8;
401    if (u64::from(netmask) << prefix) & 0xffff_ffff != 0 {
402        0
403    } else {
404        prefix
405    }
406}
407
408fn ipv6_netmask_to_prefix(netmask: Ipv6Addr) -> u8 {
409    let netmask = netmask.segments();
410    let mut mask_iter = netmask.iter();
411    let mut prefix = 0;
412    for &segment in &mut mask_iter {
413        if segment == 0xffff {
414            prefix += 16;
415        } else if segment == 0 {
416            break;
417        } else {
418            let prefix_bits = (!segment).leading_zeros() as u8;
419            if segment << prefix_bits != 0 {
420                return 0;
421            }
422            prefix += prefix_bits;
423            break;
424        }
425    }
426    for &segment in mask_iter {
427        if segment != 0 {
428            return 0;
429        }
430    }
431    prefix
432}
433
434fn prefix_to_ipv4_netmask(prefix_len: u8) -> Ipv4Addr {
435    let netmask_u32: u32 = u32::max_value()
436        .checked_shl(32 - prefix_len as u32)
437        .unwrap_or(0);
438    Ipv4Addr::from(netmask_u32)
439}
440
441fn prefix_to_ipv6_netmask(prefix_len: u8) -> Ipv6Addr {
442    let netmask_u128: u128 = u128::max_value()
443        .checked_shl((128 - prefix_len) as u32)
444        .unwrap_or(u128::min_value());
445    Ipv6Addr::from(netmask_u128)
446}
447
448#[cfg(target_endian = "little")]
449fn htonl(val: u32) -> u32 {
450    let o3 = (val >> 24) as u8;
451    let o2 = (val >> 16) as u8;
452    let o1 = (val >> 8) as u8;
453    let o0 = val as u8;
454    (o0 as u32) << 24 | (o1 as u32) << 16 | (o2 as u32) << 8 | (o3 as u32)
455}
456
457#[cfg(target_endian = "big")]
458fn htonl(val: u32) -> u32 {
459    val
460}
461
462/// Structure of MAC address
463#[derive(Clone, Debug)]
464pub struct MacAddr(u8, u8, u8, u8, u8, u8);
465
466impl MacAddr {
467    /// Construct a new MacAddr instance from the given octets
468    pub fn new(octets: [u8; 6]) -> MacAddr {
469        MacAddr(
470            octets[0], octets[1], octets[2], octets[3], octets[4], octets[5],
471        )
472    }
473    /// Returns an array of MAC address octets
474    pub fn octets(&self) -> [u8; 6] {
475        [self.0, self.1, self.2, self.3, self.4, self.5]
476    }
477    /// Return a formatted string of MAC address
478    pub fn address(&self) -> String {
479        format!(
480            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
481            self.0, self.1, self.2, self.3, self.4, self.5
482        )
483    }
484    /// Construct an all-zero MacAddr instance
485    pub fn zero() -> MacAddr {
486        MacAddr(0, 0, 0, 0, 0, 0)
487    }
488    /// Construct a new MacAddr instance from a colon-separated string of hex format
489    pub fn from_hex_format(hex_mac_addr: &str) -> MacAddr {
490        if hex_mac_addr.len() != 17 {
491            return MacAddr(0, 0, 0, 0, 0, 0);
492        }
493        let fields: Vec<&str> = hex_mac_addr.split(":").collect();
494        let o1: u8 = u8::from_str_radix(&fields[0], 0x10).unwrap_or(0);
495        let o2: u8 = u8::from_str_radix(&fields[1], 0x10).unwrap_or(0);
496        let o3: u8 = u8::from_str_radix(&fields[2], 0x10).unwrap_or(0);
497        let o4: u8 = u8::from_str_radix(&fields[3], 0x10).unwrap_or(0);
498        let o5: u8 = u8::from_str_radix(&fields[4], 0x10).unwrap_or(0);
499        let o6: u8 = u8::from_str_radix(&fields[5], 0x10).unwrap_or(0);
500        MacAddr(o1, o2, o3, o4, o5, o6)
501    }
502}
503
504impl std::fmt::Display for MacAddr {
505    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
506        let _ = write!(
507            f,
508            "{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}:{:<02x}",
509            self.0, self.1, self.2, self.3, self.4, self.5
510        );
511        Ok(())
512    }
513}