1mod tools;
2
3use crate::*;
4use serde::*;
5
6cfg_if::cfg_if! {
7 if #[cfg(any(target_os = "linux", target_os = "android"))] {
8 mod netlink;
9 use self::netlink::PlatformSupportNetlink as PlatformSupport;
10 } else if #[cfg(target_os = "windows")] {
11 mod windows;
12 mod sockaddr_tools;
13 use self::windows::PlatformSupportWindows as PlatformSupport;
14 } else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
15 mod apple;
16 mod sockaddr_tools;
17 use self::apple::PlatformSupportApple as PlatformSupport;
18 } else if #[cfg(target_os = "openbsd")] {
19 mod openbsd;
20 mod sockaddr_tools;
21 use self::openbsd::PlatformSupportOpenBSD as PlatformSupport;
22 } else if #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] {
23 mod wasm;
24 use self::wasm::PlatformSupportWasm as PlatformSupport;
25 } else {
26 compile_error!("No network interfaces support for this platform!");
27 }
28}
29
30#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Serialize, Deserialize)]
31pub enum IfAddr {
32 V4(Ifv4Addr),
33 V6(Ifv6Addr),
34}
35
36impl IfAddr {
37 #[must_use]
38 pub fn ip(&self) -> IpAddr {
39 match *self {
40 IfAddr::V4(ref ifv4_addr) => IpAddr::V4(ifv4_addr.ip),
41 IfAddr::V6(ref ifv6_addr) => IpAddr::V6(ifv6_addr.ip),
42 }
43 }
44 #[must_use]
45 pub fn netmask(&self) -> IpAddr {
46 match *self {
47 IfAddr::V4(ref ifv4_addr) => IpAddr::V4(ifv4_addr.netmask),
48 IfAddr::V6(ref ifv6_addr) => IpAddr::V6(ifv6_addr.netmask),
49 }
50 }
51 pub fn broadcast(&self) -> Option<IpAddr> {
52 match *self {
53 IfAddr::V4(ref ifv4_addr) => ifv4_addr.broadcast.map(IpAddr::V4),
54 IfAddr::V6(ref ifv6_addr) => ifv6_addr.broadcast.map(IpAddr::V6),
55 }
56 }
57
58 #[must_use]
59 pub fn network(&self) -> IfAddr {
60 match *self {
61 IfAddr::V4(ref ifv4_addr) => IfAddr::V4(ifv4_addr.network()),
62 IfAddr::V6(ref ifv6_addr) => IfAddr::V6(ifv6_addr.network()),
63 }
64 }
65
66 #[must_use]
67 pub fn contains_address(&self, addr: IpAddr) -> bool {
68 match *self {
69 IfAddr::V4(ref ifv4_addr) => match addr {
70 IpAddr::V4(ipv4_addr) => ifv4_addr.contains_address(ipv4_addr),
71 IpAddr::V6(_consensus_count) => false,
72 },
73 IfAddr::V6(ref ifv6_addr) => match addr {
74 IpAddr::V4(_) => false,
75 IpAddr::V6(ipv6_addr) => ifv6_addr.contains_address(ipv6_addr),
76 },
77 }
78 }
79}
80
81#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Serialize, Deserialize)]
83pub struct Ifv4Addr {
84 pub ip: Ipv4Addr,
86 pub netmask: Ipv4Addr,
88 pub broadcast: Option<Ipv4Addr>,
90}
91
92impl Ifv4Addr {
93 #[must_use]
95 pub fn network(&self) -> Ifv4Addr {
96 let v4 = self.ip.octets();
97 let v4mask = self.netmask.octets();
98 let ip = Ipv4Addr::new(
99 v4[0] & v4mask[0],
100 v4[1] & v4mask[1],
101 v4[2] & v4mask[2],
102 v4[3] & v4mask[3],
103 );
104 Ifv4Addr {
105 ip,
106 netmask: self.netmask,
107 broadcast: self.broadcast,
108 }
109 }
110
111 #[must_use]
112 pub fn contains_address(&self, addr: Ipv4Addr) -> bool {
113 let v4mask = self.netmask.octets();
114
115 let self_v4 = self.ip.octets();
116 let self_ip = Ipv4Addr::new(
117 self_v4[0] & v4mask[0],
118 self_v4[1] & v4mask[1],
119 self_v4[2] & v4mask[2],
120 self_v4[3] & v4mask[3],
121 );
122
123 let addr_v4 = addr.octets();
124 let addr_ip = Ipv4Addr::new(
125 addr_v4[0] & v4mask[0],
126 addr_v4[1] & v4mask[1],
127 addr_v4[2] & v4mask[2],
128 addr_v4[3] & v4mask[3],
129 );
130
131 self_ip == addr_ip
132 }
133}
134
135#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Serialize, Deserialize)]
137pub struct Ifv6Addr {
138 pub ip: Ipv6Addr,
140 pub netmask: Ipv6Addr,
142 pub broadcast: Option<Ipv6Addr>,
144}
145
146impl Ifv6Addr {
147 #[must_use]
149 pub fn network(&self) -> Ifv6Addr {
150 let v6 = self.ip.segments();
151 let v6mask = self.netmask.segments();
152 let ip = Ipv6Addr::new(
153 v6[0] & v6mask[0],
154 v6[1] & v6mask[1],
155 v6[2] & v6mask[2],
156 v6[3] & v6mask[3],
157 v6[4] & v6mask[4],
158 v6[5] & v6mask[5],
159 v6[6] & v6mask[6],
160 v6[7] & v6mask[7],
161 );
162 Ifv6Addr {
163 ip,
164 netmask: self.netmask,
165 broadcast: self.broadcast,
166 }
167 }
168
169 #[must_use]
170 pub fn contains_address(&self, addr: Ipv6Addr) -> bool {
171 let v6mask = self.netmask.segments();
172
173 let self_v6 = self.ip.segments();
174 let self_ip = Ipv6Addr::new(
175 self_v6[0] & v6mask[0],
176 self_v6[1] & v6mask[1],
177 self_v6[2] & v6mask[2],
178 self_v6[3] & v6mask[3],
179 self_v6[4] & v6mask[4],
180 self_v6[5] & v6mask[5],
181 self_v6[6] & v6mask[6],
182 self_v6[7] & v6mask[7],
183 );
184
185 let addr_v6 = addr.segments();
186 let addr_ip = Ipv6Addr::new(
187 addr_v6[0] & v6mask[0],
188 addr_v6[1] & v6mask[1],
189 addr_v6[2] & v6mask[2],
190 addr_v6[3] & v6mask[3],
191 addr_v6[4] & v6mask[4],
192 addr_v6[5] & v6mask[5],
193 addr_v6[6] & v6mask[6],
194 addr_v6[7] & v6mask[7],
195 );
196
197 self_ip == addr_ip
198 }
199}
200
201#[derive(
203 Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy, Serialize, Deserialize,
204)]
205pub struct InterfaceFlags {
206 pub is_loopback: bool,
207 pub is_running: bool,
208 pub is_point_to_point: bool,
209}
210
211#[derive(
213 Debug, Default, PartialEq, Eq, Ord, PartialOrd, Hash, Clone, Copy, Serialize, Deserialize,
214)]
215pub struct AddressFlags {
216 pub is_dynamic: bool,
218 pub is_temporary: bool,
220 pub is_preferred: bool,
221}
222
223#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
224pub struct InterfaceAddress {
225 pub if_addr: IfAddr,
226 pub flags: AddressFlags,
227}
228
229use core::cmp::Ordering;
230
231impl Ord for InterfaceAddress {
233 fn cmp(&self, other: &Self) -> Ordering {
234 match (&self.if_addr, &other.if_addr) {
235 (IfAddr::V4(a), IfAddr::V4(b)) => {
236 let ret = ipv4addr_is_global(&a.ip).cmp(&ipv4addr_is_global(&b.ip));
238 if ret != Ordering::Equal {
239 return ret;
240 }
241 let ret = ipv4addr_is_private(&a.ip).cmp(&ipv4addr_is_private(&b.ip));
243 if ret != Ordering::Equal {
244 return ret;
245 }
246 let ret = (!self.flags.is_dynamic).cmp(&!other.flags.is_dynamic);
248 if ret != Ordering::Equal {
249 return ret;
250 }
251 }
252 (IfAddr::V6(a), IfAddr::V6(b)) => {
253 let ret = self.flags.is_preferred.cmp(&other.flags.is_preferred);
255 if ret != Ordering::Equal {
256 return ret;
257 }
258 let ret = (!self.flags.is_temporary).cmp(&!other.flags.is_temporary);
260 if ret != Ordering::Equal {
261 return ret;
262 }
263 let ret = ipv6addr_is_global(&a.ip).cmp(&ipv6addr_is_global(&b.ip));
265 if ret != Ordering::Equal {
266 return ret;
267 }
268 let ret = ipv6addr_is_unique_local(&a.ip).cmp(&ipv6addr_is_unique_local(&b.ip));
270 if ret != Ordering::Equal {
271 return ret;
272 }
273 let ret = ipv6addr_is_unicast_site_local(&a.ip)
275 .cmp(&ipv6addr_is_unicast_site_local(&b.ip));
276 if ret != Ordering::Equal {
277 return ret;
278 }
279 let ret = ipv6addr_is_unicast_link_local(&a.ip)
281 .cmp(&ipv6addr_is_unicast_link_local(&b.ip));
282 if ret != Ordering::Equal {
283 return ret;
284 }
285 let ret = (!self.flags.is_dynamic).cmp(&!other.flags.is_dynamic);
287 if ret != Ordering::Equal {
288 return ret;
289 }
290 }
291 (IfAddr::V4(a), IfAddr::V6(b)) => {
292 if other.flags.is_preferred && !other.flags.is_temporary {
294 let ret = ipv4addr_is_global(&a.ip).cmp(&ipv6addr_is_global(&b.ip));
295 if ret != Ordering::Equal {
296 return ret;
297 }
298 }
299
300 return Ordering::Greater;
302 }
303 (IfAddr::V6(a), IfAddr::V4(b)) => {
304 if self.flags.is_preferred && !self.flags.is_temporary {
306 let ret = ipv6addr_is_global(&a.ip).cmp(&ipv4addr_is_global(&b.ip));
307 if ret != Ordering::Equal {
308 return ret;
309 }
310 }
311
312 return Ordering::Less;
314 }
315 }
316 let ret = self.if_addr.cmp(&other.if_addr);
318 if ret != Ordering::Equal {
319 return ret;
320 }
321 self.flags.cmp(&other.flags)
322 }
323}
324impl PartialOrd for InterfaceAddress {
325 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
326 Some(self.cmp(other))
327 }
328}
329
330impl InterfaceAddress {
331 #[must_use]
332 pub fn new(if_addr: IfAddr, flags: AddressFlags) -> Self {
333 Self { if_addr, flags }
334 }
335
336 #[must_use]
337 pub fn if_addr(&self) -> &IfAddr {
338 &self.if_addr
339 }
340
341 #[must_use]
342 pub fn is_temporary(&self) -> bool {
343 self.flags.is_temporary
344 }
345
346 #[must_use]
347 pub fn is_dynamic(&self) -> bool {
348 self.flags.is_dynamic
349 }
350
351 #[must_use]
352 pub fn is_preferred(&self) -> bool {
353 self.flags.is_preferred
354 }
355}
356
357#[derive(PartialEq, Eq, Clone, Serialize, Deserialize)]
366pub struct NetworkInterface {
367 pub name: String,
368 pub flags: InterfaceFlags,
369 pub gateways: Vec<IpAddr>,
370 pub addrs: Vec<InterfaceAddress>,
371}
372
373impl fmt::Debug for NetworkInterface {
374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375 let alt = f.alternate();
376 let mut ds = f.debug_struct("NetworkInterface");
377 ds.field("name", &self.name)
378 .field("flags", &self.flags)
379 .field("gateways", &self.gateways)
380 .field("addrs", &self.addrs);
381 if alt {
382 ds.field("// primary_ipv4", &self.primary_ipv4());
383 ds.field("// primary_ipv6", &self.primary_ipv6());
384 }
385 ds.finish()
386 }
387}
388impl NetworkInterface {
389 #[must_use]
390 pub fn new(name: String, flags: InterfaceFlags) -> Self {
391 Self {
392 name,
393 flags,
394 gateways: Vec::new(),
395 addrs: Vec::new(),
396 }
397 }
398 #[must_use]
399 pub fn name(&self) -> String {
400 self.name.clone()
401 }
402 #[must_use]
403 pub fn is_loopback(&self) -> bool {
404 self.flags.is_loopback
405 }
406
407 #[must_use]
408 pub fn is_point_to_point(&self) -> bool {
409 self.flags.is_point_to_point
410 }
411
412 #[must_use]
413 pub fn is_running(&self) -> bool {
414 self.flags.is_running
415 }
416
417 pub fn add_address(&mut self, addr: InterfaceAddress) {
418 self.addrs.push(addr);
419 self.addrs.sort();
420 self.addrs.dedup();
421 }
422
423 #[must_use]
424 pub fn addresses(&self) -> &[InterfaceAddress] {
425 &self.addrs
426 }
427
428 pub fn add_gateway(&mut self, gateway: IpAddr) {
429 self.gateways.push(gateway);
430 self.gateways.sort();
431 self.gateways.dedup();
432 }
433
434 #[must_use]
435 pub fn gateways(&self) -> &[IpAddr] {
436 &self.gateways
437 }
438
439 #[must_use]
440 pub fn primary_ipv4(&self) -> Option<InterfaceAddress> {
441 let mut ipv4addrs: Vec<&InterfaceAddress> = self
442 .addrs
443 .iter()
444 .filter(|a| matches!(a.if_addr(), IfAddr::V4(_)))
445 .collect();
446 ipv4addrs.sort();
447 ipv4addrs.last().cloned().cloned()
448 }
449
450 #[must_use]
451 pub fn primary_ipv6(&self) -> Option<InterfaceAddress> {
452 let mut ipv6addrs: Vec<&InterfaceAddress> = self
453 .addrs
454 .iter()
455 .filter(|a| matches!(a.if_addr(), IfAddr::V6(_)))
456 .collect();
457 ipv6addrs.sort();
458 ipv6addrs.last().cloned().cloned()
459 }
460}
461
462#[derive(Clone, Default, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
463pub struct NetworkInterfaceAddressState {
464 pub gateway_addresses: Vec<IpAddr>,
465 pub interface_addresses: Vec<IfAddr>,
466}
467
468pub struct NetworkInterfacesInner {
469 valid: bool,
470 interfaces: BTreeMap<String, NetworkInterface>,
471 interface_address_state_cache: Arc<NetworkInterfaceAddressState>,
472}
473
474#[derive(Clone)]
475pub struct NetworkInterfaces {
476 inner: Arc<Mutex<NetworkInterfacesInner>>,
477}
478
479impl fmt::Debug for NetworkInterfaces {
480 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
481 let inner = self.inner.lock();
482 f.debug_struct("NetworkInterfaces")
483 .field("valid", &inner.valid)
484 .field("interfaces", &inner.interfaces)
485 .finish()?;
486 if f.alternate() {
487 writeln!(f)?;
488 writeln!(
489 f,
490 "// interface_address_state_cache: {:?}",
491 inner.interface_address_state_cache
492 )?;
493 }
494 Ok(())
495 }
496}
497
498impl Default for NetworkInterfaces {
499 fn default() -> Self {
500 Self::new()
501 }
502}
503
504impl NetworkInterfaces {
505 #[must_use]
506 pub fn new() -> Self {
507 Self {
508 inner: Arc::new(Mutex::new(NetworkInterfacesInner {
509 valid: false,
510 interfaces: BTreeMap::new(),
511 interface_address_state_cache: Arc::new(NetworkInterfaceAddressState::default()),
512 })),
513 }
514 }
515
516 #[must_use]
517 pub fn is_valid(&self) -> bool {
518 let inner = self.inner.lock();
519 inner.valid
520 }
521 pub fn clear(&self) {
522 let mut inner = self.inner.lock();
523
524 inner.interfaces.clear();
525 inner.interface_address_state_cache = Arc::new(NetworkInterfaceAddressState::default());
526 inner.valid = false;
527 }
528 pub async fn refresh(&self) -> std::io::Result<bool> {
530 let mut last_interfaces = {
531 let mut last_interfaces = BTreeMap::<String, NetworkInterface>::new();
532 let mut platform_support = PlatformSupport::new();
533 platform_support
534 .get_interfaces(&mut last_interfaces)
535 .await?;
536 last_interfaces
537 };
538
539 let mut inner = self.inner.lock();
540 core::mem::swap(&mut inner.interfaces, &mut last_interfaces);
541 inner.valid = true;
542
543 if last_interfaces != inner.interfaces {
544 let old_interface_address_state = inner.interface_address_state_cache.clone();
546
547 Self::cache_interface_address_state(&mut inner);
549
550 if old_interface_address_state != inner.interface_address_state_cache {
552 return Ok(true);
553 }
554 }
555 Ok(false)
556 }
557 pub fn with_interfaces<F, R>(&self, f: F) -> R
558 where
559 F: FnOnce(&BTreeMap<String, NetworkInterface>) -> R,
560 {
561 let inner = self.inner.lock();
562 f(&inner.interfaces)
563 }
564
565 #[must_use]
566 pub fn interface_address_state(&self) -> Arc<NetworkInterfaceAddressState> {
567 let inner = self.inner.lock();
568 inner.interface_address_state_cache.clone()
569 }
570
571 fn cache_interface_address_state(inner: &mut NetworkInterfacesInner) {
574 let mut intf_addrs = Vec::new();
576 let mut gateway_addresses = Vec::new();
577 for intf in inner.interfaces.values() {
578 if !intf.is_running() || intf.is_loopback() {
579 continue;
580 }
581
582 for addr in intf.addresses() {
583 if addr.is_temporary() {
584 continue;
585 }
586 intf_addrs.push(addr.clone());
587 }
588
589 for gateway in intf.gateways() {
590 gateway_addresses.push(*gateway);
591 }
592 }
593
594 let mut interface_addresses = intf_addrs
596 .iter()
597 .map(|x| x.if_addr().clone())
598 .collect::<Vec<_>>();
599
600 interface_addresses.sort();
601 interface_addresses.dedup();
602
603 gateway_addresses.sort();
604 gateway_addresses.dedup();
605
606 inner.interface_address_state_cache = Arc::new(NetworkInterfaceAddressState {
608 gateway_addresses,
609 interface_addresses,
610 });
611 }
612}