sysinfo/common/network.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::collections::HashMap;
4use std::fmt;
5use std::net::IpAddr;
6
7use crate::{NetworkDataInner, NetworksInner};
8
9/// Interacting with network interfaces.
10///
11/// ```no_run
12/// use sysinfo::Networks;
13///
14/// let networks = Networks::new_with_refreshed_list();
15/// for (interface_name, network) in &networks {
16/// println!("[{interface_name}]: {network:?}");
17/// }
18/// ```
19pub struct Networks {
20 pub(crate) inner: NetworksInner,
21}
22
23impl<'a> IntoIterator for &'a Networks {
24 type Item = (&'a String, &'a NetworkData);
25 type IntoIter = std::collections::hash_map::Iter<'a, String, NetworkData>;
26
27 fn into_iter(self) -> Self::IntoIter {
28 self.iter()
29 }
30}
31
32impl Default for Networks {
33 fn default() -> Self {
34 Networks::new()
35 }
36}
37
38impl Networks {
39 /// Creates a new empty [`Networks`][crate::Networks] type.
40 ///
41 /// If you want it to be filled directly, take a look at [`Networks::new_with_refreshed_list`].
42 ///
43 /// ```no_run
44 /// use sysinfo::Networks;
45 ///
46 /// let mut networks = Networks::new();
47 /// networks.refresh(true);
48 /// for (interface_name, network) in &networks {
49 /// println!("[{interface_name}]: {network:?}");
50 /// }
51 /// ```
52 pub fn new() -> Self {
53 Self {
54 inner: NetworksInner::new(),
55 }
56 }
57
58 /// Creates a new [`Networks`][crate::Networks] type with the network interfaces
59 /// list loaded.
60 ///
61 /// ```no_run
62 /// use sysinfo::Networks;
63 ///
64 /// let networks = Networks::new_with_refreshed_list();
65 /// for network in &networks {
66 /// println!("{network:?}");
67 /// }
68 /// ```
69 pub fn new_with_refreshed_list() -> Self {
70 let mut networks = Self::new();
71 networks.refresh(false);
72 networks
73 }
74
75 /// Returns the network interfaces map.
76 ///
77 /// ```no_run
78 /// use sysinfo::Networks;
79 ///
80 /// let networks = Networks::new_with_refreshed_list();
81 /// for network in networks.list() {
82 /// println!("{network:?}");
83 /// }
84 /// ```
85 pub fn list(&self) -> &HashMap<String, NetworkData> {
86 self.inner.list()
87 }
88
89 /// Refreshes the network interfaces.
90 ///
91 /// ```no_run
92 /// use sysinfo::Networks;
93 ///
94 /// let mut networks = Networks::new_with_refreshed_list();
95 /// // Wait some time...? Then refresh the data of each network.
96 /// networks.refresh(true);
97 /// ```
98 pub fn refresh(&mut self, remove_not_listed_interfaces: bool) {
99 self.inner.refresh(remove_not_listed_interfaces)
100 }
101}
102
103impl std::ops::Deref for Networks {
104 type Target = HashMap<String, NetworkData>;
105
106 fn deref(&self) -> &Self::Target {
107 self.list()
108 }
109}
110
111/// Getting volume of received and transmitted data.
112///
113/// ```no_run
114/// use sysinfo::Networks;
115///
116/// let networks = Networks::new_with_refreshed_list();
117/// for (interface_name, network) in &networks {
118/// println!("[{interface_name}] {network:?}");
119/// }
120/// ```
121pub struct NetworkData {
122 pub(crate) inner: NetworkDataInner,
123}
124
125impl NetworkData {
126 /// Returns the number of received bytes since the last refresh.
127 ///
128 /// If you want the total number of bytes received, take a look at the
129 /// [`total_received`](NetworkData::total_received) method.
130 ///
131 /// ```no_run
132 /// use sysinfo::Networks;
133 /// use std::{thread, time};
134 ///
135 /// let mut networks = Networks::new_with_refreshed_list();
136 /// // Waiting a bit to get data from network...
137 /// thread::sleep(time::Duration::from_millis(10));
138 /// // Refreshing again to generate diff.
139 /// networks.refresh(true);
140 ///
141 /// for (interface_name, network) in &networks {
142 /// println!("in: {} B", network.received());
143 /// }
144 /// ```
145 pub fn received(&self) -> u64 {
146 self.inner.received()
147 }
148
149 /// Returns the total number of received bytes.
150 ///
151 /// If you want the amount of received bytes since the last refresh, take a look at the
152 /// [`received`](NetworkData::received) method.
153 ///
154 /// ```no_run
155 /// use sysinfo::Networks;
156 ///
157 /// let networks = Networks::new_with_refreshed_list();
158 /// for (interface_name, network) in &networks {
159 /// println!("in: {} B", network.total_received());
160 /// }
161 /// ```
162 pub fn total_received(&self) -> u64 {
163 self.inner.total_received()
164 }
165
166 /// Returns the number of transmitted bytes since the last refresh.
167 ///
168 /// If you want the total number of bytes transmitted, take a look at the
169 /// [`total_transmitted`](NetworkData::total_transmitted) method.
170 ///
171 /// ```no_run
172 /// use sysinfo::Networks;
173 /// use std::{thread, time};
174 ///
175 /// let mut networks = Networks::new_with_refreshed_list();
176 /// // Waiting a bit to get data from network...
177 /// thread::sleep(time::Duration::from_millis(10));
178 /// // Refreshing again to generate diff.
179 /// networks.refresh(true);
180 ///
181 /// for (interface_name, network) in &networks {
182 /// println!("out: {} B", network.transmitted());
183 /// }
184 /// ```
185 pub fn transmitted(&self) -> u64 {
186 self.inner.transmitted()
187 }
188
189 /// Returns the total number of transmitted bytes.
190 ///
191 /// If you want the amount of transmitted bytes since the last refresh, take a look at the
192 /// [`transmitted`](NetworkData::transmitted) method.
193 ///
194 /// ```no_run
195 /// use sysinfo::Networks;
196 ///
197 /// let networks = Networks::new_with_refreshed_list();
198 /// for (interface_name, network) in &networks {
199 /// println!("out: {} B", network.total_transmitted());
200 /// }
201 /// ```
202 pub fn total_transmitted(&self) -> u64 {
203 self.inner.total_transmitted()
204 }
205
206 /// Returns the number of incoming packets since the last refresh.
207 ///
208 /// If you want the total number of packets received, take a look at the
209 /// [`total_packets_received`](NetworkData::total_packets_received) method.
210 ///
211 /// ```no_run
212 /// use sysinfo::Networks;
213 /// use std::{thread, time};
214 ///
215 /// let mut networks = Networks::new_with_refreshed_list();
216 /// // Waiting a bit to get data from network...
217 /// thread::sleep(time::Duration::from_millis(10));
218 /// // Refreshing again to generate diff.
219 /// networks.refresh(true);
220 ///
221 /// for (interface_name, network) in &networks {
222 /// println!("in: {}", network.packets_received());
223 /// }
224 /// ```
225 pub fn packets_received(&self) -> u64 {
226 self.inner.packets_received()
227 }
228
229 /// Returns the total number of incoming packets.
230 ///
231 /// If you want the amount of received packets since the last refresh, take a look at the
232 /// [`packets_received`](NetworkData::packets_received) method.
233 ///
234 /// ```no_run
235 /// use sysinfo::Networks;
236 ///
237 /// let networks = Networks::new_with_refreshed_list();
238 /// for (interface_name, network) in &networks {
239 /// println!("in: {}", network.total_packets_received());
240 /// }
241 /// ```
242 pub fn total_packets_received(&self) -> u64 {
243 self.inner.total_packets_received()
244 }
245
246 /// Returns the number of outcoming packets since the last refresh.
247 ///
248 /// If you want the total number of packets transmitted, take a look at the
249 /// [`total_packets_transmitted`](NetworkData::total_packets_transmitted) method.
250 ///
251 /// ```no_run
252 /// use sysinfo::Networks;
253 /// use std::{thread, time};
254 ///
255 /// let mut networks = Networks::new_with_refreshed_list();
256 /// // Waiting a bit to get data from network...
257 /// thread::sleep(time::Duration::from_millis(10));
258 /// // Refreshing again to generate diff.
259 /// networks.refresh(true);
260 ///
261 /// for (interface_name, network) in &networks {
262 /// println!("out: {}", network.packets_transmitted());
263 /// }
264 /// ```
265 pub fn packets_transmitted(&self) -> u64 {
266 self.inner.packets_transmitted()
267 }
268
269 /// Returns the total number of outcoming packets.
270 ///
271 /// If you want the amount of transmitted packets since the last refresh, take a look at the
272 /// [`packets_transmitted`](NetworkData::packets_transmitted) method.
273 ///
274 /// ```no_run
275 /// use sysinfo::Networks;
276 ///
277 /// let networks = Networks::new_with_refreshed_list();
278 /// for (interface_name, network) in &networks {
279 /// println!("out: {}", network.total_packets_transmitted());
280 /// }
281 /// ```
282 pub fn total_packets_transmitted(&self) -> u64 {
283 self.inner.total_packets_transmitted()
284 }
285
286 /// Returns the number of incoming errors since the last refresh.
287 ///
288 /// If you want the total number of errors on received packets, take a look at the
289 /// [`total_errors_on_received`](NetworkData::total_errors_on_received) method.
290 ///
291 /// ```no_run
292 /// use sysinfo::Networks;
293 /// use std::{thread, time};
294 ///
295 /// let mut networks = Networks::new_with_refreshed_list();
296 /// // Waiting a bit to get data from network...
297 /// thread::sleep(time::Duration::from_millis(10));
298 /// // Refreshing again to generate diff.
299 /// networks.refresh(true);
300 ///
301 /// for (interface_name, network) in &networks {
302 /// println!("in: {}", network.errors_on_received());
303 /// }
304 /// ```
305 pub fn errors_on_received(&self) -> u64 {
306 self.inner.errors_on_received()
307 }
308
309 /// Returns the total number of incoming errors.
310 ///
311 /// If you want the amount of errors on received packets since the last refresh, take a look at
312 /// the [`errors_on_received`](NetworkData::errors_on_received) method.
313 ///
314 /// ```no_run
315 /// use sysinfo::Networks;
316 ///
317 /// let networks = Networks::new_with_refreshed_list();
318 /// for (interface_name, network) in &networks {
319 /// println!("in: {}", network.total_errors_on_received());
320 /// }
321 /// ```
322 pub fn total_errors_on_received(&self) -> u64 {
323 self.inner.total_errors_on_received()
324 }
325
326 /// Returns the number of outcoming errors since the last refresh.
327 ///
328 /// If you want the total number of errors on transmitted packets, take a look at the
329 /// [`total_errors_on_transmitted`](NetworkData::total_errors_on_transmitted) method.
330 ///
331 /// ```no_run
332 /// use sysinfo::Networks;
333 /// use std::{thread, time};
334 ///
335 /// let mut networks = Networks::new_with_refreshed_list();
336 /// // Waiting a bit to get data from network...
337 /// thread::sleep(time::Duration::from_millis(10));
338 /// // Refreshing again to generate diff.
339 /// networks.refresh(true);
340 ///
341 /// for (interface_name, network) in &networks {
342 /// println!("out: {}", network.errors_on_transmitted());
343 /// }
344 /// ```
345 pub fn errors_on_transmitted(&self) -> u64 {
346 self.inner.errors_on_transmitted()
347 }
348
349 /// Returns the total number of outcoming errors.
350 ///
351 /// If you want the amount of errors on transmitted packets since the last refresh, take a look at
352 /// the [`errors_on_transmitted`](NetworkData::errors_on_transmitted) method.
353 ///
354 /// ```no_run
355 /// use sysinfo::Networks;
356 ///
357 /// let networks = Networks::new_with_refreshed_list();
358 /// for (interface_name, network) in &networks {
359 /// println!("out: {}", network.total_errors_on_transmitted());
360 /// }
361 /// ```
362 pub fn total_errors_on_transmitted(&self) -> u64 {
363 self.inner.total_errors_on_transmitted()
364 }
365
366 /// Returns the MAC address associated to current interface.
367 ///
368 /// ```no_run
369 /// use sysinfo::Networks;
370 ///
371 /// let mut networks = Networks::new_with_refreshed_list();
372 /// for (interface_name, network) in &networks {
373 /// println!("MAC address: {}", network.mac_address());
374 /// }
375 /// ```
376 pub fn mac_address(&self) -> MacAddr {
377 self.inner.mac_address()
378 }
379
380 /// Returns the Ip Networks associated to current interface.
381 ///
382 /// ```no_run
383 /// use sysinfo::Networks;
384 ///
385 /// let mut networks = Networks::new_with_refreshed_list();
386 /// for (interface_name, network) in &networks {
387 /// println!("Ip Networks: {:?}", network.ip_networks());
388 /// }
389 /// ```
390 pub fn ip_networks(&self) -> &[IpNetwork] {
391 self.inner.ip_networks()
392 }
393
394 /// Returns the Maximum Transfer Unit (MTU) of the interface.
395 ///
396 /// ```no_run
397 /// use sysinfo::Networks;
398 ///
399 /// let mut networks = Networks::new_with_refreshed_list();
400 /// for (interface_name, network) in &networks {
401 /// println!("mtu: {}", network.mtu());
402 /// }
403 /// ```
404 pub fn mtu(&self) -> u64 {
405 self.inner.mtu()
406 }
407}
408
409/// MAC address for network interface.
410///
411/// It is returned by [`NetworkData::mac_address`][crate::NetworkData::mac_address].
412#[derive(PartialEq, Eq, Copy, Clone, Debug)]
413pub struct MacAddr(pub [u8; 6]);
414
415impl MacAddr {
416 /// A `MacAddr` with all bytes set to `0`.
417 pub const UNSPECIFIED: Self = MacAddr([0; 6]);
418
419 /// Checks if this `MacAddr` has all bytes equal to `0`.
420 pub fn is_unspecified(&self) -> bool {
421 self == &MacAddr::UNSPECIFIED
422 }
423}
424
425impl fmt::Display for MacAddr {
426 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427 let data = &self.0;
428 write!(
429 f,
430 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
431 data[0], data[1], data[2], data[3], data[4], data[5],
432 )
433 }
434}
435
436/// Ip networks address for network interface.
437///
438/// It is returned by [`NetworkData::ip_networks`][crate::NetworkData::ip_networks].
439#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
440pub struct IpNetwork {
441 /// The ip of the network interface
442 pub addr: IpAddr,
443 /// The netmask, prefix of the ipaddress
444 pub prefix: u8,
445}
446
447impl fmt::Display for IpNetwork {
448 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
449 write!(f, "{}/{}", self.addr, self.prefix)
450 }
451}
452
453#[cfg(test)]
454mod tests {
455 use crate::*;
456 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
457
458 // Ensure that the `Display` and `Debug` traits are implemented on the `MacAddr` struct
459 #[test]
460 fn check_display_impl_mac_address() {
461 println!(
462 "{} {:?}",
463 MacAddr([0x1, 0x2, 0x3, 0x4, 0x5, 0x6]),
464 MacAddr([0xa, 0xb, 0xc, 0xd, 0xe, 0xf])
465 );
466 }
467
468 #[test]
469 fn check_mac_address_is_unspecified_true() {
470 assert!(MacAddr::UNSPECIFIED.is_unspecified());
471 assert!(MacAddr([0; 6]).is_unspecified());
472 }
473
474 #[test]
475 fn check_mac_address_is_unspecified_false() {
476 assert!(!MacAddr([1, 2, 3, 4, 5, 6]).is_unspecified());
477 }
478
479 // Ensure that the `Display` and `Debug` traits are implemented on the `IpNetwork` struct
480 #[test]
481 fn check_display_impl_ip_network_ipv4() {
482 println!(
483 "{} {:?}",
484 IpNetwork {
485 addr: IpAddr::from(Ipv4Addr::new(1, 2, 3, 4)),
486 prefix: 3
487 },
488 IpNetwork {
489 addr: IpAddr::from(Ipv4Addr::new(255, 255, 255, 0)),
490 prefix: 21
491 }
492 );
493 }
494
495 #[test]
496 fn check_display_impl_ip_network_ipv6() {
497 println!(
498 "{} {:?}",
499 IpNetwork {
500 addr: IpAddr::from(Ipv6Addr::new(0xffff, 0xaabb, 00, 0, 0, 0x000c, 11, 21)),
501 prefix: 127
502 },
503 IpNetwork {
504 addr: IpAddr::from(Ipv6Addr::new(0xffcc, 0, 0, 0xffcc, 0, 0xffff, 0, 0xccaa)),
505 prefix: 120
506 }
507 )
508 }
509
510 #[test]
511 fn check_ip_networks() {
512 if !IS_SUPPORTED_SYSTEM {
513 return;
514 }
515 let networks = Networks::new_with_refreshed_list();
516 if networks.iter().any(|(_, n)| !n.ip_networks().is_empty()) {
517 return;
518 }
519 panic!("Networks should have at least one IP network ");
520 }
521}