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#[derive(Clone, Debug)]
16pub struct Interface {
17 pub index: u32,
19 pub name: String,
21 pub friendly_name: Option<String>,
23 pub description: Option<String>,
25 pub if_type: InterfaceType,
27 pub mac_addr: Option<MacAddr>,
29 pub ipv4: Vec<Ipv4Net>,
31 pub ipv6: Vec<Ipv6Net>,
33 pub flags: u32,
35 pub transmit_speed: Option<u64>,
37 pub receive_speed: Option<u64>,
39 pub gateway: Option<Gateway>,
41}
42
43#[derive(Clone, Debug)]
45pub struct Gateway {
46 pub mac_addr: MacAddr,
48 pub ip_addr: IpAddr,
50}
51
52impl Gateway {
53 pub fn new() -> Gateway {
55 Gateway {
56 mac_addr: MacAddr::zero(),
57 ip_addr: IpAddr::V4(Ipv4Addr::UNSPECIFIED),
58 }
59 }
60}
61pub 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
89pub 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
104pub 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#[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#[cfg(not(target_os = "windows"))]
127pub fn get_default_gateway_macaddr() -> [u8; 6] {
128 MacAddr::zero().octets()
129}
130
131#[derive(Clone, Copy, Debug, PartialEq)]
133pub enum InterfaceType {
134 Unknown,
136 Ethernet,
138 TokenRing,
140 Fddi,
142 BasicIsdn,
144 PrimaryIsdn,
146 Ppp,
148 Loopback,
150 Ethernet3Megabit,
152 Slip,
154 Atm,
156 GenericModem,
158 FastEthernetT,
160 Isdn,
162 FastEthernetFx,
164 Wireless80211,
166 AsymmetricDsl,
168 RateAdaptDsl,
170 SymmetricDsl,
172 VeryHighSpeedDsl,
174 IPOverAtm,
176 GigabitEthernet,
178 Tunnel,
180 MultiRateSymmetricDsl,
182 HighPerformanceSerialBus,
184 Wman,
186 Wwanpp,
188 Wwanpp2,
190}
191
192impl InterfaceType {
193 #[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 #[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 #[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 match *self {
255 _ => 0,
256 }
257 }
258 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#[derive(Clone, Debug)]
340pub struct Ipv4Net {
341 pub addr: Ipv4Addr,
343 pub prefix_len: u8,
345 pub netmask: Ipv4Addr,
347}
348
349impl Ipv4Net {
350 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 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#[derive(Clone, Debug)]
370pub struct Ipv6Net {
371 pub addr: Ipv6Addr,
373 pub prefix_len: u8,
375 pub netmask: Ipv6Addr,
377}
378
379impl Ipv6Net {
380 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 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#[derive(Clone, Debug)]
464pub struct MacAddr(u8, u8, u8, u8, u8, u8);
465
466impl MacAddr {
467 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 pub fn octets(&self) -> [u8; 6] {
475 [self.0, self.1, self.2, self.3, self.4, self.5]
476 }
477 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 pub fn zero() -> MacAddr {
486 MacAddr(0, 0, 0, 0, 0, 0)
487 }
488 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}