1#![allow(clippy::manual_strip)]
4
5use crate::ProcResult;
10use crate::{build_internal_error, expect, from_iter, from_str};
11use std::collections::HashMap;
12
13use bitflags::bitflags;
14use std::io::BufRead;
15use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
16use std::{path::PathBuf, str::FromStr};
17
18#[cfg(feature = "serde1")]
19use serde::{Deserialize, Serialize};
20
21#[derive(Debug, Clone, PartialEq, Eq)]
22#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
23pub enum TcpState {
24 Established = 1,
25 SynSent,
26 SynRecv,
27 FinWait1,
28 FinWait2,
29 TimeWait,
30 Close,
31 CloseWait,
32 LastAck,
33 Listen,
34 Closing,
35 NewSynRecv,
36}
37
38impl TcpState {
39 pub fn from_u8(num: u8) -> Option<TcpState> {
40 match num {
41 0x01 => Some(TcpState::Established),
42 0x02 => Some(TcpState::SynSent),
43 0x03 => Some(TcpState::SynRecv),
44 0x04 => Some(TcpState::FinWait1),
45 0x05 => Some(TcpState::FinWait2),
46 0x06 => Some(TcpState::TimeWait),
47 0x07 => Some(TcpState::Close),
48 0x08 => Some(TcpState::CloseWait),
49 0x09 => Some(TcpState::LastAck),
50 0x0A => Some(TcpState::Listen),
51 0x0B => Some(TcpState::Closing),
52 0x0C => Some(TcpState::NewSynRecv),
53 _ => None,
54 }
55 }
56
57 pub fn to_u8(&self) -> u8 {
58 match self {
59 TcpState::Established => 0x01,
60 TcpState::SynSent => 0x02,
61 TcpState::SynRecv => 0x03,
62 TcpState::FinWait1 => 0x04,
63 TcpState::FinWait2 => 0x05,
64 TcpState::TimeWait => 0x06,
65 TcpState::Close => 0x07,
66 TcpState::CloseWait => 0x08,
67 TcpState::LastAck => 0x09,
68 TcpState::Listen => 0x0A,
69 TcpState::Closing => 0x0B,
70 TcpState::NewSynRecv => 0x0C,
71 }
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
76#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
77pub enum UdpState {
78 Established = 1,
79 Close = 7,
80}
81
82impl UdpState {
83 pub fn from_u8(num: u8) -> Option<UdpState> {
84 match num {
85 0x01 => Some(UdpState::Established),
86 0x07 => Some(UdpState::Close),
87 _ => None,
88 }
89 }
90
91 pub fn to_u8(&self) -> u8 {
92 match self {
93 UdpState::Established => 0x01,
94 UdpState::Close => 0x07,
95 }
96 }
97}
98
99#[derive(Debug, Clone, PartialEq, Eq)]
100#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
101pub enum UnixState {
102 UNCONNECTED = 1,
103 CONNECTING = 2,
104 CONNECTED = 3,
105 DISCONNECTING = 4,
106}
107
108impl UnixState {
109 pub fn from_u8(num: u8) -> Option<UnixState> {
110 match num {
111 0x01 => Some(UnixState::UNCONNECTED),
112 0x02 => Some(UnixState::CONNECTING),
113 0x03 => Some(UnixState::CONNECTED),
114 0x04 => Some(UnixState::DISCONNECTING),
115 _ => None,
116 }
117 }
118
119 pub fn to_u8(&self) -> u8 {
120 match self {
121 UnixState::UNCONNECTED => 0x01,
122 UnixState::CONNECTING => 0x02,
123 UnixState::CONNECTED => 0x03,
124 UnixState::DISCONNECTING => 0x04,
125 }
126 }
127}
128
129#[derive(Debug, Clone)]
131#[non_exhaustive]
132#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
133pub struct TcpNetEntry {
134 pub local_address: SocketAddr,
135 pub remote_address: SocketAddr,
136 pub state: TcpState,
137 pub rx_queue: u32,
138 pub tx_queue: u32,
139 pub uid: u32,
140 pub inode: u64,
141}
142
143#[derive(Debug, Clone)]
145#[non_exhaustive]
146#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
147pub struct UdpNetEntry {
148 pub local_address: SocketAddr,
149 pub remote_address: SocketAddr,
150 pub state: UdpState,
151 pub rx_queue: u32,
152 pub tx_queue: u32,
153 pub uid: u32,
154 pub inode: u64,
155}
156
157#[derive(Debug, Clone)]
159#[non_exhaustive]
160#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
161pub struct UnixNetEntry {
162 pub ref_count: u32,
164 pub socket_type: u16,
169 pub state: UnixState,
171 pub inode: u64,
173 pub path: Option<PathBuf>,
178}
179
180fn parse_addressport_str(s: &str, little_endian: bool) -> ProcResult<SocketAddr> {
184 let mut las = s.split(':');
185 let ip_part = expect!(las.next(), "ip_part");
186 let port = expect!(las.next(), "port");
187 let port = from_str!(u16, port, 16);
188
189 use std::convert::TryInto;
190
191 let read_u32 = if little_endian {
192 u32::from_le_bytes
193 } else {
194 u32::from_be_bytes
195 };
196
197 if ip_part.len() == 8 {
198 let bytes = expect!(hex::decode(ip_part));
199 let ip_u32 = read_u32(bytes[..4].try_into().unwrap());
200
201 let ip = Ipv4Addr::from(ip_u32);
202
203 Ok(SocketAddr::V4(SocketAddrV4::new(ip, port)))
204 } else if ip_part.len() == 32 {
205 let bytes = expect!(hex::decode(ip_part));
206
207 let ip_a = read_u32(bytes[0..4].try_into().unwrap());
208 let ip_b = read_u32(bytes[4..8].try_into().unwrap());
209 let ip_c = read_u32(bytes[8..12].try_into().unwrap());
210 let ip_d = read_u32(bytes[12..16].try_into().unwrap());
211
212 let ip = Ipv6Addr::new(
213 ((ip_a >> 16) & 0xffff) as u16,
214 (ip_a & 0xffff) as u16,
215 ((ip_b >> 16) & 0xffff) as u16,
216 (ip_b & 0xffff) as u16,
217 ((ip_c >> 16) & 0xffff) as u16,
218 (ip_c & 0xffff) as u16,
219 ((ip_d >> 16) & 0xffff) as u16,
220 (ip_d & 0xffff) as u16,
221 );
222
223 Ok(SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)))
224 } else {
225 Err(build_internal_error!(format!(
226 "Unable to parse {:?} as an address:port",
227 s
228 )))
229 }
230}
231
232#[derive(Debug, Clone)]
234#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
235pub struct TcpNetEntries(pub Vec<TcpNetEntry>);
236
237impl super::FromBufReadSI for TcpNetEntries {
238 fn from_buf_read<R: BufRead>(r: R, system_info: &crate::SystemInfo) -> ProcResult<Self> {
239 let mut vec = Vec::new();
240
241 for line in r.lines().skip(1) {
243 let line = line?;
244 let mut s = line.split_whitespace();
245 s.next();
246 let local_address = expect!(s.next(), "tcp::local_address");
247 let rem_address = expect!(s.next(), "tcp::rem_address");
248 let state = expect!(s.next(), "tcp::st");
249 let mut tx_rx_queue = expect!(s.next(), "tcp::tx_queue:rx_queue").splitn(2, ':');
250 let tx_queue = from_str!(u32, expect!(tx_rx_queue.next(), "tcp::tx_queue"), 16);
251 let rx_queue = from_str!(u32, expect!(tx_rx_queue.next(), "tcp::rx_queue"), 16);
252 s.next(); s.next(); let uid = from_str!(u32, expect!(s.next(), "tcp::uid"));
255 s.next(); let inode = expect!(s.next(), "tcp::inode");
257
258 vec.push(TcpNetEntry {
259 local_address: parse_addressport_str(local_address, system_info.is_little_endian())?,
260 remote_address: parse_addressport_str(rem_address, system_info.is_little_endian())?,
261 rx_queue,
262 tx_queue,
263 state: expect!(TcpState::from_u8(from_str!(u8, state, 16))),
264 uid,
265 inode: from_str!(u64, inode),
266 });
267 }
268
269 Ok(TcpNetEntries(vec))
270 }
271}
272
273#[derive(Debug, Clone)]
275#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
276pub struct UdpNetEntries(pub Vec<UdpNetEntry>);
277
278impl super::FromBufReadSI for UdpNetEntries {
279 fn from_buf_read<R: BufRead>(r: R, system_info: &crate::SystemInfo) -> ProcResult<Self> {
280 let mut vec = Vec::new();
281
282 for line in r.lines().skip(1) {
284 let line = line?;
285 let mut s = line.split_whitespace();
286 s.next();
287 let local_address = expect!(s.next(), "udp::local_address");
288 let rem_address = expect!(s.next(), "udp::rem_address");
289 let state = expect!(s.next(), "udp::st");
290 let mut tx_rx_queue = expect!(s.next(), "udp::tx_queue:rx_queue").splitn(2, ':');
291 let tx_queue: u32 = from_str!(u32, expect!(tx_rx_queue.next(), "udp::tx_queue"), 16);
292 let rx_queue: u32 = from_str!(u32, expect!(tx_rx_queue.next(), "udp::rx_queue"), 16);
293 s.next(); s.next(); let uid = from_str!(u32, expect!(s.next(), "udp::uid"));
296 s.next(); let inode = expect!(s.next(), "udp::inode");
298
299 vec.push(UdpNetEntry {
300 local_address: parse_addressport_str(local_address, system_info.is_little_endian())?,
301 remote_address: parse_addressport_str(rem_address, system_info.is_little_endian())?,
302 rx_queue,
303 tx_queue,
304 state: expect!(UdpState::from_u8(from_str!(u8, state, 16))),
305 uid,
306 inode: from_str!(u64, inode),
307 });
308 }
309
310 Ok(UdpNetEntries(vec))
311 }
312}
313
314#[derive(Debug, Clone)]
316#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
317pub struct UnixNetEntries(pub Vec<UnixNetEntry>);
318
319impl super::FromBufRead for UnixNetEntries {
320 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
321 let mut vec = Vec::new();
322
323 for line in r.lines().skip(1) {
325 let line = line?;
326 let mut s = line.split_whitespace();
327 s.next(); let ref_count = from_str!(u32, expect!(s.next()), 16);
329 s.next(); s.next(); let socket_type = from_str!(u16, expect!(s.next()), 16);
332 let state = from_str!(u8, expect!(s.next()), 16);
333 let inode = from_str!(u64, expect!(s.next()));
334 let path = s.next().map(PathBuf::from);
335
336 vec.push(UnixNetEntry {
337 ref_count,
338 socket_type,
339 inode,
340 state: expect!(UnixState::from_u8(state)),
341 path,
342 });
343 }
344
345 Ok(UnixNetEntries(vec))
346 }
347}
348
349#[derive(Debug, Clone)]
351#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
352pub struct ARPEntry {
353 pub ip_address: Ipv4Addr,
355 pub hw_type: ARPHardware,
359 pub flags: ARPFlags,
361 pub hw_address: Option<[u8; 6]>,
363 pub device: String,
365}
366
367bitflags! {
368 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
371 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
372 pub struct ARPHardware: u32 {
373 const NETROM = 0;
375 const ETHER = 1;
377 const EETHER = 2;
379 const AX25 = 3;
381 const PRONET = 4;
383 const CHAOS = 5;
385 const IEEE802 = 6;
387 const ARCNET = 7;
389 const APPLETLK = 8;
391 const DLCI = 15;
393 const ATM = 19;
395 const METRICOM = 23;
397 const IEEE1394 = 24;
399 const EUI64 = 27;
401 const INFINIBAND = 32;
403 }
404}
405
406bitflags! {
407 #[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
410 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
411 pub struct ARPFlags: u32 {
412 const COM = 0x02;
414 const PERM = 0x04;
416 const PUBL = 0x08;
418 const USETRAILERS = 0x10;
420 const NETMASK = 0x20;
422 const DONTPUB = 0x40;
424 }
425}
426
427#[derive(Debug, Clone)]
429#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
430pub struct ArpEntries(pub Vec<ARPEntry>);
431
432impl super::FromBufRead for ArpEntries {
433 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
434 let mut vec = Vec::new();
435
436 for line in r.lines().skip(1) {
438 let line = line?;
440 let mut line = line.split_whitespace();
441 let ip_address = expect!(Ipv4Addr::from_str(expect!(line.next())));
442 let hw = from_str!(u32, &expect!(line.next())[2..], 16);
443 let hw = ARPHardware::from_bits_truncate(hw);
444 let flags = from_str!(u32, &expect!(line.next())[2..], 16);
445 let flags = ARPFlags::from_bits_truncate(flags);
446
447 let mac = expect!(line.next());
448 let mut mac: Vec<Result<u8, _>> = mac.split(':').map(|s| Ok(from_str!(u8, s, 16))).collect();
449
450 let mac = if mac.len() == 6 {
451 let mac_block_f = mac.pop().unwrap()?;
452 let mac_block_e = mac.pop().unwrap()?;
453 let mac_block_d = mac.pop().unwrap()?;
454 let mac_block_c = mac.pop().unwrap()?;
455 let mac_block_b = mac.pop().unwrap()?;
456 let mac_block_a = mac.pop().unwrap()?;
457 if mac_block_a == 0
458 && mac_block_b == 0
459 && mac_block_c == 0
460 && mac_block_d == 0
461 && mac_block_e == 0
462 && mac_block_f == 0
463 {
464 None
465 } else {
466 Some([
467 mac_block_a,
468 mac_block_b,
469 mac_block_c,
470 mac_block_d,
471 mac_block_e,
472 mac_block_f,
473 ])
474 }
475 } else {
476 None
477 };
478
479 let _mask = expect!(line.next());
481 let dev = expect!(line.next());
482
483 vec.push(ARPEntry {
484 ip_address,
485 hw_type: hw,
486 flags,
487 hw_address: mac,
488 device: dev.to_string(),
489 })
490 }
491
492 Ok(ArpEntries(vec))
493 }
494}
495
496#[derive(Debug, Clone)]
501#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
502pub struct DeviceStatus {
503 pub name: String,
505 pub recv_bytes: u64,
507 pub recv_packets: u64,
509 pub recv_errs: u64,
511 pub recv_drop: u64,
513 pub recv_fifo: u64,
515 pub recv_frame: u64,
517 pub recv_compressed: u64,
519 pub recv_multicast: u64,
521
522 pub sent_bytes: u64,
524 pub sent_packets: u64,
526 pub sent_errs: u64,
528 pub sent_drop: u64,
530 pub sent_fifo: u64,
531 pub sent_colls: u64,
533 pub sent_carrier: u64,
535 pub sent_compressed: u64,
537}
538
539impl DeviceStatus {
540 fn from_str(s: &str) -> ProcResult<DeviceStatus> {
541 let mut split = s.split_whitespace();
542 let name: String = expect!(from_iter(&mut split));
543 let recv_bytes = expect!(from_iter(&mut split));
544 let recv_packets = expect!(from_iter(&mut split));
545 let recv_errs = expect!(from_iter(&mut split));
546 let recv_drop = expect!(from_iter(&mut split));
547 let recv_fifo = expect!(from_iter(&mut split));
548 let recv_frame = expect!(from_iter(&mut split));
549 let recv_compressed = expect!(from_iter(&mut split));
550 let recv_multicast = expect!(from_iter(&mut split));
551 let sent_bytes = expect!(from_iter(&mut split));
552 let sent_packets = expect!(from_iter(&mut split));
553 let sent_errs = expect!(from_iter(&mut split));
554 let sent_drop = expect!(from_iter(&mut split));
555 let sent_fifo = expect!(from_iter(&mut split));
556 let sent_colls = expect!(from_iter(&mut split));
557 let sent_carrier = expect!(from_iter(&mut split));
558 let sent_compressed = expect!(from_iter(&mut split));
559
560 Ok(DeviceStatus {
561 name: name.trim_end_matches(':').to_owned(),
562 recv_bytes,
563 recv_packets,
564 recv_errs,
565 recv_drop,
566 recv_fifo,
567 recv_frame,
568 recv_compressed,
569 recv_multicast,
570 sent_bytes,
571 sent_packets,
572 sent_errs,
573 sent_drop,
574 sent_fifo,
575 sent_colls,
576 sent_carrier,
577 sent_compressed,
578 })
579 }
580}
581
582#[derive(Debug, Clone)]
584#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
585pub struct InterfaceDeviceStatus(pub HashMap<String, DeviceStatus>);
586
587impl super::FromBufRead for InterfaceDeviceStatus {
588 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
589 let mut map = HashMap::new();
590 for line in r.lines().skip(2) {
592 let dev = DeviceStatus::from_str(&line?)?;
593 map.insert(dev.name.clone(), dev);
594 }
595
596 Ok(InterfaceDeviceStatus(map))
597 }
598}
599
600#[derive(Debug, Clone)]
602#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
603pub struct RouteEntry {
604 pub iface: String,
606 pub destination: Ipv4Addr,
608 pub gateway: Ipv4Addr,
609 pub flags: u16,
610 pub refcnt: u16,
612 pub in_use: u16,
614 pub metrics: u32,
616 pub mask: Ipv4Addr,
617 pub mtu: u32,
619 pub window: u32,
621 pub irtt: u32,
623}
624
625#[derive(Debug, Clone)]
627#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
628pub struct RouteEntries(pub Vec<RouteEntry>);
629
630impl super::FromBufRead for RouteEntries {
631 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
632 let mut vec = Vec::new();
633
634 for line in r.lines().skip(1) {
636 let line = line?;
638 let mut line = line.split_whitespace();
639 let iface = expect!(line.next());
641 let destination = from_str!(u32, expect!(line.next()), 16).to_ne_bytes().into();
642 let gateway = from_str!(u32, expect!(line.next()), 16).to_ne_bytes().into();
643 let flags = from_str!(u16, expect!(line.next()), 16);
644 let refcnt = from_str!(u16, expect!(line.next()), 10);
645 let in_use = from_str!(u16, expect!(line.next()), 10);
646 let metrics = from_str!(u32, expect!(line.next()), 10);
647 let mask = from_str!(u32, expect!(line.next()), 16).to_ne_bytes().into();
648 let mtu = from_str!(u32, expect!(line.next()), 10);
649 let window = from_str!(u32, expect!(line.next()), 10);
650 let irtt = from_str!(u32, expect!(line.next()), 10);
651 vec.push(RouteEntry {
652 iface: iface.to_string(),
653 destination,
654 gateway,
655 flags,
656 refcnt,
657 in_use,
658 metrics,
659 mask,
660 mtu,
661 window,
662 irtt,
663 });
664 }
665
666 Ok(RouteEntries(vec))
667 }
668}
669
670#[derive(Debug, Clone, PartialEq, Eq)]
671#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
672pub enum IpForwarding {
682 Forwarding = 1,
684 NotForwarding = 2,
686}
687
688impl IpForwarding {
689 pub fn from_u8(num: u8) -> Option<IpForwarding> {
690 match num {
691 1 => Some(IpForwarding::Forwarding),
692 2 => Some(IpForwarding::NotForwarding),
693 _ => None,
694 }
695 }
696
697 pub fn to_u8(&self) -> u8 {
698 match self {
699 IpForwarding::Forwarding => 1,
700 IpForwarding::NotForwarding => 2,
701 }
702 }
703}
704
705#[derive(Debug, Clone, PartialEq, Eq)]
706#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
707pub enum TcpRtoAlgorithm {
710 Other = 1,
712 Constant = 2,
714 Rsre = 3,
716 Vanj = 4,
720}
721
722impl TcpRtoAlgorithm {
723 pub fn from_u8(num: u8) -> Option<TcpRtoAlgorithm> {
724 match num {
725 1 => Some(TcpRtoAlgorithm::Other),
726 2 => Some(TcpRtoAlgorithm::Constant),
727 3 => Some(TcpRtoAlgorithm::Rsre),
728 4 => Some(TcpRtoAlgorithm::Vanj),
729 _ => None,
730 }
731 }
732
733 pub fn to_u8(&self) -> u8 {
734 match self {
735 TcpRtoAlgorithm::Other => 1,
736 TcpRtoAlgorithm::Constant => 2,
737 TcpRtoAlgorithm::Rsre => 3,
738 TcpRtoAlgorithm::Vanj => 4,
739 }
740 }
741}
742
743#[derive(Debug, Clone)]
749#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
750pub struct Snmp {
751 pub ip_forwarding: IpForwarding,
752 pub ip_default_ttl: u32,
756 pub ip_in_receives: u64,
759 pub ip_in_hdr_errors: u64,
762 pub ip_in_addr_errors: u64,
766 pub ip_forw_datagrams: u64,
770 pub ip_in_unknown_protos: u64,
773 pub ip_in_discards: u64,
777 pub ip_in_delivers: u64,
783 pub ip_out_requests: u64,
789 pub ip_out_discards: u64,
797 pub ip_out_no_routes: u64,
806 pub ip_reasm_timeout: u64,
809 pub ip_reasm_reqds: u64,
812 pub ip_reasm_oks: u64,
814 pub ip_reasm_fails: u64,
822 pub ip_frag_oks: u64,
825 pub ip_frag_fails: u64,
829 pub ip_frag_creates: u64,
832
833 pub icmp_in_msgs: u64,
837 pub icmp_in_errors: u64,
840 pub icmp_in_csum_errors: u64,
844 pub icmp_in_dest_unreachs: u64,
846 pub icmp_in_time_excds: u64,
848 pub icmp_in_parm_probs: u64,
850 pub icmp_in_src_quenchs: u64,
852 pub icmp_in_redirects: u64,
854 pub icmp_in_echos: u64,
856 pub icmp_in_echo_reps: u64,
858 pub icmp_in_timestamps: u64,
860 pub icmp_in_timestamp_reps: u64,
862 pub icmp_in_addr_masks: u64,
864 pub icmp_in_addr_mask_reps: u64,
866 pub icmp_out_msgs: u64,
870 pub icmp_out_errors: u64,
877 pub icmp_out_dest_unreachs: u64,
879 pub icmp_out_time_excds: u64,
881 pub icmp_out_parm_probs: u64,
883 pub icmp_out_src_quenchs: u64,
885 pub icmp_out_redirects: u64,
888 pub icmp_out_echos: u64,
890 pub icmp_out_echo_reps: u64,
892 pub icmp_out_timestamps: u64,
894 pub icmp_out_timestamp_reps: u64,
896 pub icmp_out_addr_masks: u64,
898 pub icmp_out_addr_mask_reps: u64,
900
901 pub tcp_rto_algorithm: TcpRtoAlgorithm,
903 pub tcp_rto_min: u64,
910 pub tcp_rto_max: u64,
917 pub tcp_max_conn: i64,
921 pub tcp_active_opens: u64,
924 pub tcp_passive_opens: u64,
927 pub tcp_attempt_fails: u64,
932 pub tcp_estab_resets: u64,
935 pub tcp_curr_estab: u64,
938 pub tcp_in_segs: u64,
942 pub tcp_out_segs: u64,
945 pub tcp_retrans_segs: u64,
948 pub tcp_in_errs: u64,
950 pub tcp_out_rsts: u64,
952 pub tcp_in_csum_errors: u64,
956
957 pub udp_in_datagrams: u64,
959 pub udp_no_ports: u64,
962 pub udp_in_errors: u64,
965 pub udp_out_datagrams: u64,
967 pub udp_rcvbuf_errors: u64,
971 pub udp_sndbuf_errors: u64,
975 pub udp_in_csum_errors: u64,
979 pub udp_ignored_multi: u64,
983
984 pub udp_lite_in_datagrams: u64,
988 pub udp_lite_no_ports: u64,
992 pub udp_lite_in_errors: u64,
996 pub udp_lite_out_datagrams: u64,
1000 pub udp_lite_rcvbuf_errors: u64,
1004 pub udp_lite_sndbuf_errors: u64,
1008 pub udp_lite_in_csum_errors: u64,
1012 pub udp_lite_ignored_multi: u64,
1016}
1017
1018#[derive(Debug)]
1026struct SnmpSection {
1027 prefix: String,
1028 values: HashMap<String, String>,
1029}
1030
1031impl<'a> SnmpSection {
1032 fn new(hdr: String, data: String) -> ProcResult<Self> {
1033 let mut hdr = hdr.trim_end().split_whitespace();
1034 let mut data = data.trim_end().split_whitespace();
1035 let prefix = expect!(hdr.next()).to_owned();
1036 expect!(data.next());
1037 let mut values = HashMap::new();
1038
1039 for hdr in hdr {
1040 values.insert(hdr.to_owned(), expect!(data.next()).to_owned());
1041 }
1042
1043 Ok(Self { prefix, values })
1044 }
1045}
1046
1047#[derive(Debug)]
1049struct SnmpSections<B> {
1050 buf: B,
1051}
1052
1053impl<B: BufRead> Iterator for SnmpSections<B> {
1054 type Item = ProcResult<SnmpSection>;
1055
1056 fn next(&mut self) -> Option<Self::Item> {
1057 let mut hdr = String::new();
1058 match self.buf.read_line(&mut hdr) {
1059 Ok(0) => None,
1060 Ok(_n) => {
1061 let mut data = String::new();
1062 match self.buf.read_line(&mut data) {
1063 Ok(_n) => Some(SnmpSection::new(hdr, data)),
1064 Err(e) => Some(Err(e.into())),
1065 }
1066 }
1067 Err(e) => Some(Err(e.into())),
1068 }
1069 }
1070}
1071
1072impl super::FromBufRead for Snmp {
1073 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
1074 let mut map = HashMap::new();
1075 let sections = SnmpSections { buf: r };
1076 for section in sections.flatten() {
1077 let p = §ion.prefix;
1078 for (hdr, v) in §ion.values {
1079 map.insert(format!("{p}{hdr}"), v.to_owned());
1080 }
1081 }
1082
1083 let snmp = Snmp {
1084 ip_forwarding: expect!(IpForwarding::from_u8(from_str!(
1086 u8,
1087 &expect!(map.remove("Ip:Forwarding"))
1088 ))),
1089 ip_default_ttl: from_str!(u32, &expect!(map.remove("Ip:DefaultTTL"))),
1090 ip_in_receives: from_str!(u64, &expect!(map.remove("Ip:InReceives"))),
1091 ip_in_hdr_errors: from_str!(u64, &expect!(map.remove("Ip:InHdrErrors"))),
1092 ip_in_addr_errors: from_str!(u64, &expect!(map.remove("Ip:InAddrErrors"))),
1093 ip_forw_datagrams: from_str!(u64, &expect!(map.remove("Ip:ForwDatagrams"))),
1094 ip_in_unknown_protos: from_str!(u64, &expect!(map.remove("Ip:InUnknownProtos"))),
1095 ip_in_discards: from_str!(u64, &expect!(map.remove("Ip:InDiscards"))),
1096 ip_in_delivers: from_str!(u64, &expect!(map.remove("Ip:InDelivers"))),
1097 ip_out_requests: from_str!(u64, &expect!(map.remove("Ip:OutRequests"))),
1098 ip_out_discards: from_str!(u64, &expect!(map.remove("Ip:OutDiscards"))),
1099 ip_out_no_routes: from_str!(u64, &expect!(map.remove("Ip:OutNoRoutes"))),
1100 ip_reasm_timeout: from_str!(u64, &expect!(map.remove("Ip:ReasmTimeout"))),
1101 ip_reasm_reqds: from_str!(u64, &expect!(map.remove("Ip:ReasmReqds"))),
1102 ip_reasm_oks: from_str!(u64, &expect!(map.remove("Ip:ReasmOKs"))),
1103 ip_reasm_fails: from_str!(u64, &expect!(map.remove("Ip:ReasmFails"))),
1104 ip_frag_oks: from_str!(u64, &expect!(map.remove("Ip:FragOKs"))),
1105 ip_frag_fails: from_str!(u64, &expect!(map.remove("Ip:FragFails"))),
1106 ip_frag_creates: from_str!(u64, &expect!(map.remove("Ip:FragCreates"))),
1107 icmp_in_msgs: from_str!(u64, &expect!(map.remove("Icmp:InMsgs"))),
1110 icmp_in_errors: from_str!(u64, &expect!(map.remove("Icmp:InErrors"))),
1111 icmp_in_csum_errors: from_str!(u64, &expect!(map.remove("Icmp:InCsumErrors"))),
1112 icmp_in_dest_unreachs: from_str!(u64, &expect!(map.remove("Icmp:InDestUnreachs"))),
1113 icmp_in_time_excds: from_str!(u64, &expect!(map.remove("Icmp:InTimeExcds"))),
1114 icmp_in_parm_probs: from_str!(u64, &expect!(map.remove("Icmp:InParmProbs"))),
1115 icmp_in_src_quenchs: from_str!(u64, &expect!(map.remove("Icmp:InSrcQuenchs"))),
1116 icmp_in_redirects: from_str!(u64, &expect!(map.remove("Icmp:InRedirects"))),
1117 icmp_in_echos: from_str!(u64, &expect!(map.remove("Icmp:InEchos"))),
1118 icmp_in_echo_reps: from_str!(u64, &expect!(map.remove("Icmp:InEchoReps"))),
1119 icmp_in_timestamps: from_str!(u64, &expect!(map.remove("Icmp:InTimestamps"))),
1120 icmp_in_timestamp_reps: from_str!(u64, &expect!(map.remove("Icmp:InTimestampReps"))),
1121 icmp_in_addr_masks: from_str!(u64, &expect!(map.remove("Icmp:InAddrMasks"))),
1122 icmp_in_addr_mask_reps: from_str!(u64, &expect!(map.remove("Icmp:InAddrMaskReps"))),
1123 icmp_out_msgs: from_str!(u64, &expect!(map.remove("Icmp:OutMsgs"))),
1124 icmp_out_errors: from_str!(u64, &expect!(map.remove("Icmp:OutErrors"))),
1125 icmp_out_dest_unreachs: from_str!(u64, &expect!(map.remove("Icmp:OutDestUnreachs"))),
1128 icmp_out_time_excds: from_str!(u64, &expect!(map.remove("Icmp:OutTimeExcds"))),
1129 icmp_out_parm_probs: from_str!(u64, &expect!(map.remove("Icmp:OutParmProbs"))),
1130 icmp_out_src_quenchs: from_str!(u64, &expect!(map.remove("Icmp:OutSrcQuenchs"))),
1131 icmp_out_redirects: from_str!(u64, &expect!(map.remove("Icmp:OutRedirects"))),
1132 icmp_out_echos: from_str!(u64, &expect!(map.remove("Icmp:OutEchos"))),
1133 icmp_out_echo_reps: from_str!(u64, &expect!(map.remove("Icmp:OutEchoReps"))),
1134 icmp_out_timestamps: from_str!(u64, &expect!(map.remove("Icmp:OutTimestamps"))),
1135 icmp_out_timestamp_reps: from_str!(u64, &expect!(map.remove("Icmp:OutTimestampReps"))),
1136 icmp_out_addr_masks: from_str!(u64, &expect!(map.remove("Icmp:OutAddrMasks"))),
1137 icmp_out_addr_mask_reps: from_str!(u64, &expect!(map.remove("Icmp:OutAddrMaskReps"))),
1138 tcp_rto_algorithm: expect!(TcpRtoAlgorithm::from_u8(from_str!(
1140 u8,
1141 &expect!(map.remove("Tcp:RtoAlgorithm"))
1142 ))),
1143 tcp_rto_min: from_str!(u64, &expect!(map.remove("Tcp:RtoMin"))),
1144 tcp_rto_max: from_str!(u64, &expect!(map.remove("Tcp:RtoMax"))),
1145 tcp_max_conn: from_str!(i64, &expect!(map.remove("Tcp:MaxConn"))),
1146 tcp_active_opens: from_str!(u64, &expect!(map.remove("Tcp:ActiveOpens"))),
1147 tcp_passive_opens: from_str!(u64, &expect!(map.remove("Tcp:PassiveOpens"))),
1148 tcp_attempt_fails: from_str!(u64, &expect!(map.remove("Tcp:AttemptFails"))),
1149 tcp_estab_resets: from_str!(u64, &expect!(map.remove("Tcp:EstabResets"))),
1150 tcp_curr_estab: from_str!(u64, &expect!(map.remove("Tcp:CurrEstab"))),
1151 tcp_in_segs: from_str!(u64, &expect!(map.remove("Tcp:InSegs"))),
1152 tcp_out_segs: from_str!(u64, &expect!(map.remove("Tcp:OutSegs"))),
1153 tcp_retrans_segs: from_str!(u64, &expect!(map.remove("Tcp:RetransSegs"))),
1154 tcp_in_errs: from_str!(u64, &expect!(map.remove("Tcp:InErrs"))),
1155 tcp_out_rsts: from_str!(u64, &expect!(map.remove("Tcp:OutRsts"))),
1156 tcp_in_csum_errors: from_str!(u64, &expect!(map.remove("Tcp:InCsumErrors"))),
1157 udp_in_datagrams: from_str!(u64, &expect!(map.remove("Udp:InDatagrams"))),
1159 udp_no_ports: from_str!(u64, &expect!(map.remove("Udp:NoPorts"))),
1160 udp_in_errors: from_str!(u64, &expect!(map.remove("Udp:InErrors"))),
1161 udp_out_datagrams: from_str!(u64, &expect!(map.remove("Udp:OutDatagrams"))),
1162 udp_rcvbuf_errors: from_str!(u64, &expect!(map.remove("Udp:RcvbufErrors"))),
1163 udp_sndbuf_errors: from_str!(u64, &expect!(map.remove("Udp:SndbufErrors"))),
1164 udp_in_csum_errors: from_str!(u64, &expect!(map.remove("Udp:InCsumErrors"))),
1165 udp_ignored_multi: from_str!(u64, &expect!(map.remove("Udp:IgnoredMulti"))),
1166 udp_lite_in_datagrams: from_str!(u64, &expect!(map.remove("UdpLite:InDatagrams"))),
1169 udp_lite_no_ports: from_str!(u64, &expect!(map.remove("UdpLite:NoPorts"))),
1170 udp_lite_in_errors: from_str!(u64, &expect!(map.remove("UdpLite:InErrors"))),
1171 udp_lite_out_datagrams: from_str!(u64, &expect!(map.remove("UdpLite:OutDatagrams"))),
1172 udp_lite_rcvbuf_errors: from_str!(u64, &expect!(map.remove("UdpLite:RcvbufErrors"))),
1173 udp_lite_sndbuf_errors: from_str!(u64, &expect!(map.remove("UdpLite:SndbufErrors"))),
1174 udp_lite_in_csum_errors: from_str!(u64, &expect!(map.remove("UdpLite:InCsumErrors"))),
1175 udp_lite_ignored_multi: from_str!(u64, &expect!(map.remove("UdpLite:IgnoredMulti"))),
1176 };
1178
1179 Ok(snmp)
1180 }
1181}
1182
1183#[derive(Debug, Clone)]
1191#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
1192pub struct Snmp6 {
1193 pub ip_in_receives: u64,
1196 pub ip_in_hdr_errors: u64,
1199 pub ip_in_too_big_errors: u64,
1203 pub ip_in_no_routes: u64,
1207 pub ip_in_addr_errors: u64,
1211 pub ip_in_unknown_protos: u64,
1214 pub ip_in_truncated_pkts: u64,
1218 pub ip_in_discards: u64,
1222 pub ip_in_delivers: u64,
1228 pub ip_out_forw_datagrams: u64,
1232 pub ip_out_requests: u64,
1238 pub ip_out_discards: u64,
1246 pub ip_out_no_routes: u64,
1255 pub ip_reasm_timeout: u64,
1258 pub ip_reasm_reqds: u64,
1261 pub ip_reasm_oks: u64,
1263 pub ip_reasm_fails: u64,
1271 pub ip_frag_oks: u64,
1274 pub ip_frag_fails: u64,
1278 pub ip_frag_creates: u64,
1281 pub ip_in_mcast_pkts: u64,
1285 pub ip_out_mcast_pkts: u64,
1289 pub ip_in_octets: u64,
1293 pub ip_out_octets: u64,
1297 pub ip_in_mcast_octets: u64,
1301 pub ip_out_mcast_octets: u64,
1305 pub ip_in_bcast_octets: u64,
1309 pub ip_out_bcast_octets: u64,
1313 pub ip_in_no_ect_pkts: u64,
1317 pub ip_in_ect1_pkts: u64,
1321 pub ip_in_ect0_pkts: u64,
1325 pub ip_in_ce_pkts: u64,
1329
1330 pub icmp_in_msgs: u64,
1334 pub icmp_in_errors: u64,
1337 pub icmp_out_msgs: u64,
1341 pub icmp_out_errors: u64,
1348 pub icmp_in_csum_errors: u64,
1352 pub icmp_in_dest_unreachs: u64,
1354 pub icmp_in_pkt_too_bigs: u64,
1358 pub icmp_in_time_excds: u64,
1360 pub icmp_in_parm_problem: u64,
1362 pub icmp_in_echos: u64,
1364 pub icmp_in_echo_replies: u64,
1366 pub icmp_in_group_memb_queries: u64,
1370 pub icmp_in_group_memb_responses: u64,
1374 pub icmp_in_group_memb_reductions: u64,
1378 pub icmp_in_router_solicits: u64,
1382 pub icmp_in_router_advertisements: u64,
1386 pub icmp_in_neighbor_solicits: u64,
1390 pub icmp_in_neighbor_advertisements: u64,
1394 pub icmp_in_redirects: u64,
1398 pub icmp_in_mldv2_reports: u64,
1402 pub icmp_out_dest_unreachs: u64,
1404 pub icmp_out_pkt_too_bigs: u64,
1408 pub icmp_out_time_excds: u64,
1410 pub icmp_out_parm_problems: u64,
1412 pub icmp_out_echos: u64,
1414 pub icmp_out_echo_replies: u64,
1416 pub icmp_out_group_memb_queries: u64,
1420 pub icmp_out_group_memb_responses: u64,
1424 pub icmp_out_group_memb_reductions: u64,
1428 pub icmp_out_router_solicits: u64,
1432 pub icmp_out_router_advertisements: u64,
1436 pub icmp_out_neighbor_solicits: u64,
1440 pub icmp_out_neighbor_advertisements: u64,
1444 pub icmp_out_redirects: u64,
1448 pub icmp_out_mldv2_reports: u64,
1452 pub udp_in_datagrams: u64,
1457 pub udp_no_ports: u64,
1460 pub udp_in_errors: u64,
1463 pub udp_out_datagrams: u64,
1465 pub udp_rcvbuf_errors: u64,
1469 pub udp_sndbuf_errors: u64,
1473 pub udp_in_csum_errors: u64,
1477 pub udp_ignored_multi: u64,
1481
1482 pub udp_lite_in_datagrams: u64,
1486 pub udp_lite_no_ports: u64,
1490 pub udp_lite_in_errors: u64,
1494 pub udp_lite_out_datagrams: u64,
1498 pub udp_lite_rcvbuf_errors: u64,
1502 pub udp_lite_sndbuf_errors: u64,
1506 pub udp_lite_in_csum_errors: u64,
1510}
1511
1512impl super::FromBufRead for Snmp6 {
1513 fn from_buf_read<R: BufRead>(r: R) -> ProcResult<Self> {
1514 let mut map = HashMap::new();
1515
1516 for line in r.lines() {
1517 let line = expect!(line);
1518 if line.is_empty() {
1519 continue;
1520 }
1521 let mut s = line.split_whitespace();
1522 let field = expect!(s.next(), "no field");
1523 if field.starts_with("Icmp6InType") || field.starts_with("Icmp6OutType") {
1524 continue;
1525 }
1526 let value = from_str!(u64, expect!(s.next(), "no value"));
1527 map.insert(field.to_string(), value);
1528 }
1529
1530 let snmp6 = Snmp6 {
1531 ip_in_receives: expect!(map.remove("Ip6InReceives")),
1532 ip_in_hdr_errors: expect!(map.remove("Ip6InHdrErrors")),
1533 ip_in_too_big_errors: expect!(map.remove("Ip6InTooBigErrors")),
1534 ip_in_no_routes: expect!(map.remove("Ip6InNoRoutes")),
1535 ip_in_addr_errors: expect!(map.remove("Ip6InAddrErrors")),
1536 ip_in_unknown_protos: expect!(map.remove("Ip6InUnknownProtos")),
1537 ip_in_truncated_pkts: expect!(map.remove("Ip6InTruncatedPkts")),
1538 ip_in_discards: expect!(map.remove("Ip6InDiscards")),
1539 ip_in_delivers: expect!(map.remove("Ip6InDelivers")),
1540 ip_out_forw_datagrams: expect!(map.remove("Ip6OutForwDatagrams")),
1541 ip_out_requests: expect!(map.remove("Ip6OutRequests")),
1542 ip_out_discards: expect!(map.remove("Ip6OutDiscards")),
1543 ip_out_no_routes: expect!(map.remove("Ip6OutNoRoutes")),
1544 ip_reasm_timeout: expect!(map.remove("Ip6ReasmTimeout")),
1545 ip_reasm_reqds: expect!(map.remove("Ip6ReasmReqds")),
1546 ip_reasm_oks: expect!(map.remove("Ip6ReasmOKs")),
1547 ip_reasm_fails: expect!(map.remove("Ip6ReasmFails")),
1548 ip_frag_oks: expect!(map.remove("Ip6FragOKs")),
1549 ip_frag_fails: expect!(map.remove("Ip6FragFails")),
1550 ip_frag_creates: expect!(map.remove("Ip6FragCreates")),
1551 ip_in_mcast_pkts: expect!(map.remove("Ip6InMcastPkts")),
1552 ip_out_mcast_pkts: expect!(map.remove("Ip6OutMcastPkts")),
1553 ip_in_octets: expect!(map.remove("Ip6InOctets")),
1554 ip_out_octets: expect!(map.remove("Ip6OutOctets")),
1555 ip_in_mcast_octets: expect!(map.remove("Ip6InMcastOctets")),
1556 ip_out_mcast_octets: expect!(map.remove("Ip6OutMcastOctets")),
1557 ip_in_bcast_octets: expect!(map.remove("Ip6InBcastOctets")),
1558 ip_out_bcast_octets: expect!(map.remove("Ip6OutBcastOctets")),
1559 ip_in_no_ect_pkts: expect!(map.remove("Ip6InNoECTPkts")),
1560 ip_in_ect1_pkts: expect!(map.remove("Ip6InECT1Pkts")),
1561 ip_in_ect0_pkts: expect!(map.remove("Ip6InECT0Pkts")),
1562 ip_in_ce_pkts: expect!(map.remove("Ip6InCEPkts")),
1563
1564 icmp_in_msgs: expect!(map.remove("Icmp6InMsgs")),
1565 icmp_in_errors: expect!(map.remove("Icmp6InErrors")),
1566 icmp_out_msgs: expect!(map.remove("Icmp6OutMsgs")),
1567 icmp_out_errors: expect!(map.remove("Icmp6OutErrors")),
1568 icmp_in_csum_errors: expect!(map.remove("Icmp6InCsumErrors")),
1569 icmp_in_dest_unreachs: expect!(map.remove("Icmp6InDestUnreachs")),
1570 icmp_in_pkt_too_bigs: expect!(map.remove("Icmp6InPktTooBigs")),
1571 icmp_in_time_excds: expect!(map.remove("Icmp6InTimeExcds")),
1572 icmp_in_parm_problem: expect!(map.remove("Icmp6InParmProblems")),
1573 icmp_in_echos: expect!(map.remove("Icmp6InEchos")),
1574 icmp_in_echo_replies: expect!(map.remove("Icmp6InEchoReplies")),
1575 icmp_in_group_memb_queries: expect!(map.remove("Icmp6InGroupMembQueries")),
1576 icmp_in_group_memb_responses: expect!(map.remove("Icmp6InGroupMembResponses")),
1577 icmp_in_group_memb_reductions: expect!(map.remove("Icmp6InGroupMembReductions")),
1578 icmp_in_router_solicits: expect!(map.remove("Icmp6InRouterSolicits")),
1579 icmp_in_router_advertisements: expect!(map.remove("Icmp6InRouterAdvertisements")),
1580 icmp_in_neighbor_solicits: expect!(map.remove("Icmp6InNeighborSolicits")),
1581 icmp_in_neighbor_advertisements: expect!(map.remove("Icmp6InNeighborAdvertisements")),
1582 icmp_in_redirects: expect!(map.remove("Icmp6InRedirects")),
1583 icmp_in_mldv2_reports: expect!(map.remove("Icmp6InMLDv2Reports")),
1584 icmp_out_dest_unreachs: expect!(map.remove("Icmp6OutDestUnreachs")),
1585 icmp_out_pkt_too_bigs: expect!(map.remove("Icmp6OutPktTooBigs")),
1586 icmp_out_time_excds: expect!(map.remove("Icmp6OutTimeExcds")),
1587 icmp_out_parm_problems: expect!(map.remove("Icmp6OutParmProblems")),
1588 icmp_out_echos: expect!(map.remove("Icmp6OutEchos")),
1589 icmp_out_echo_replies: expect!(map.remove("Icmp6OutEchoReplies")),
1590 icmp_out_group_memb_queries: expect!(map.remove("Icmp6OutGroupMembQueries")),
1591 icmp_out_group_memb_responses: expect!(map.remove("Icmp6OutGroupMembResponses")),
1592 icmp_out_group_memb_reductions: expect!(map.remove("Icmp6OutGroupMembReductions")),
1593 icmp_out_router_solicits: expect!(map.remove("Icmp6OutRouterSolicits")),
1594 icmp_out_router_advertisements: expect!(map.remove("Icmp6OutRouterAdvertisements")),
1595 icmp_out_neighbor_solicits: expect!(map.remove("Icmp6OutNeighborSolicits")),
1596 icmp_out_neighbor_advertisements: expect!(map.remove("Icmp6OutNeighborAdvertisements")),
1597 icmp_out_redirects: expect!(map.remove("Icmp6OutRedirects")),
1598 icmp_out_mldv2_reports: expect!(map.remove("Icmp6OutMLDv2Reports")),
1599
1600 udp_in_datagrams: expect!(map.remove("Udp6InDatagrams")),
1604 udp_no_ports: expect!(map.remove("Udp6NoPorts")),
1605 udp_in_errors: expect!(map.remove("Udp6InErrors")),
1606 udp_out_datagrams: expect!(map.remove("Udp6OutDatagrams")),
1607 udp_rcvbuf_errors: expect!(map.remove("Udp6RcvbufErrors")),
1608 udp_sndbuf_errors: expect!(map.remove("Udp6SndbufErrors")),
1609 udp_in_csum_errors: expect!(map.remove("Udp6InCsumErrors")),
1610 udp_ignored_multi: expect!(map.remove("Udp6IgnoredMulti")),
1611
1612 udp_lite_in_datagrams: expect!(map.remove("UdpLite6InDatagrams")),
1613 udp_lite_no_ports: expect!(map.remove("UdpLite6NoPorts")),
1614 udp_lite_in_errors: expect!(map.remove("UdpLite6InErrors")),
1615 udp_lite_out_datagrams: expect!(map.remove("UdpLite6OutDatagrams")),
1616 udp_lite_rcvbuf_errors: expect!(map.remove("UdpLite6RcvbufErrors")),
1617 udp_lite_sndbuf_errors: expect!(map.remove("UdpLite6SndbufErrors")),
1618 udp_lite_in_csum_errors: expect!(map.remove("UdpLite6InCsumErrors")),
1619 };
1620
1621 if cfg!(test) {
1622 assert!(map.is_empty(), "snmp6 map is not empty: {:#?}", map);
1623 }
1624
1625 Ok(snmp6)
1626 }
1627}
1628
1629#[cfg(test)]
1630mod tests {
1631 use super::*;
1632 use std::net::IpAddr;
1633
1634 #[test]
1635 fn test_parse_ipaddr() {
1636 use std::str::FromStr;
1637
1638 let addr = parse_addressport_str("0100007F:1234", true).unwrap();
1639 assert_eq!(addr.port(), 0x1234);
1640 match addr.ip() {
1641 IpAddr::V4(addr) => assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1)),
1642 _ => panic!("Not IPv4"),
1643 }
1644
1645 let addr = parse_addressport_str("5014002A14080140000000000E200000:0050", true).unwrap();
1649 assert_eq!(addr.port(), 80);
1650 match addr.ip() {
1651 IpAddr::V6(addr) => assert_eq!(addr, Ipv6Addr::from_str("2a00:1450:4001:814::200e").unwrap()),
1652 _ => panic!("Not IPv6"),
1653 }
1654
1655 let addr = parse_addressport_str("B80D01200000000067452301EFCDAB89:0", true).unwrap();
1657 assert_eq!(addr.port(), 0);
1658 match addr.ip() {
1659 IpAddr::V6(addr) => assert_eq!(addr, Ipv6Addr::from_str("2001:db8::123:4567:89ab:cdef").unwrap()),
1660 _ => panic!("Not IPv6"),
1661 }
1662
1663 let addr = parse_addressport_str("1234:1234", true);
1664 assert!(addr.is_err());
1665 }
1666
1667 #[test]
1668 fn test_tcpstate_from() {
1669 assert_eq!(TcpState::from_u8(0xA).unwrap(), TcpState::Listen);
1670 }
1671
1672 #[test]
1673 fn test_snmp_debian_6_8_12() {
1674 let data = r#"Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates OutTransmits
1676Ip: 1 64 58881328 0 1 0 0 0 58879082 12449667 9745 1855 0 4 2 0 0 0 0 12449667
1677Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutRateLimitGlobal OutRateLimitHost OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
1678Icmp: 16667 83 0 16667 0 0 0 0 0 0 0 0 0 0 21854 0 2 81 21854 0 0 0 0 0 0 0 0 0 0
1679IcmpMsg: InType3 OutType3
1680IcmpMsg: 16667 21854
1681Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
1682Tcp: 1 200 120000 -1 88170 33742 29003 4952 9 5129401 4676076 3246 60 40857 0
1683Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti MemErrors
1684Udp: 48327329 21522 6981741 9605045 6981727 9497 14 478236 0
1685UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti MemErrors
1686UdpLite: 0 0 0 0 0 0 0 0 0
1687"#;
1688
1689 let r = std::io::Cursor::new(data.as_bytes());
1690 use crate::FromRead;
1691 let res = Snmp::from_read(r).unwrap();
1692 assert_eq!(res.ip_forwarding, IpForwarding::Forwarding);
1693 assert_eq!(res.ip_in_receives, 58881328);
1694 assert_eq!(res.ip_in_delivers, 58879082);
1695 assert_eq!(res.ip_out_requests, 12449667);
1696 assert_eq!(res.ip_out_no_routes, 1855);
1697 assert_eq!(res.tcp_rto_algorithm, TcpRtoAlgorithm::Other);
1698 assert_eq!(res.tcp_rto_min, 200);
1699 assert_eq!(res.tcp_rto_max, 120000);
1700 assert_eq!(res.tcp_max_conn, -1);
1701 assert_eq!(res.tcp_curr_estab, 9);
1702 assert_eq!(res.tcp_in_segs, 5129401);
1703 assert_eq!(res.tcp_out_segs, 4676076);
1704 assert_eq!(res.udp_in_datagrams, 48327329);
1705 assert_eq!(res.udp_in_csum_errors, 14);
1706 assert_eq!(res.udp_no_ports, 21522);
1707 assert_eq!(res.udp_out_datagrams, 9605045);
1708 println!("{res:?}");
1709 }
1710
1711 #[test]
1712 fn test_snmp_missing_icmp_msg() {
1713 let data = r#"Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates OutTransmits
1715Ip: 2 64 12063 0 1 0 0 0 11952 8953 0 0 0 0 0 0 0 0 0 8953
1716Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutRateLimitGlobal OutRateLimitHost OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
1717Icmp: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1718Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors
1719Tcp: 1 200 120000 -1 177 14 0 6 4 11155 10083 18 0 94 0
1720Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti MemErrors
1721Udp: 2772 0 0 1890 0 0 0 745 0
1722UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti MemErrors
1723UdpLite: 0 0 0 0 0 0 0 0 0
1724"#;
1725
1726 let r = std::io::Cursor::new(data.as_bytes());
1727 use crate::FromRead;
1728 let res = Snmp::from_read(r).unwrap();
1729 println!("{res:?}");
1730 }
1731}