netstat/integrations/linux/
api.rs

1use integrations::linux::netlink_iterator::*;
2use integrations::linux::procfs::*;
3use libc::*;
4use types::*;
5
6/// Iterate through sockets information.
7pub fn iterate_sockets_info(
8    af_flags: AddressFamilyFlags,
9    proto_flags: ProtocolFlags,
10) -> Result<impl Iterator<Item = Result<SocketInfo, Error>>, Error> {
11    let ipv4 = af_flags.contains(AddressFamilyFlags::IPV4);
12    let ipv6 = af_flags.contains(AddressFamilyFlags::IPV6);
13    let tcp = proto_flags.contains(ProtocolFlags::TCP);
14    let udp = proto_flags.contains(ProtocolFlags::UDP);
15    let mut iterators = Vec::with_capacity(4);
16    unsafe {
17        if ipv4 {
18            if tcp {
19                iterators.push(NetlinkIterator::new(AF_INET as u8, IPPROTO_TCP as u8)?);
20            }
21            if udp {
22                iterators.push(NetlinkIterator::new(AF_INET as u8, IPPROTO_UDP as u8)?);
23            }
24        }
25        if ipv6 {
26            if tcp {
27                iterators.push(NetlinkIterator::new(AF_INET6 as u8, IPPROTO_TCP as u8)?);
28            }
29            if udp {
30                iterators.push(NetlinkIterator::new(AF_INET6 as u8, IPPROTO_UDP as u8)?);
31            }
32        }
33    }
34    Ok(attach_pids(iterators.into_iter().flatten()))
35}
36
37fn attach_pids(
38    sockets_info: impl Iterator<Item = Result<SocketInfo, Error>>,
39) -> impl Iterator<Item = Result<SocketInfo, Error>> {
40    let mut pids_by_inode = build_hash_of_pids_by_inode();
41    sockets_info.map(move |r| {
42        r.map(|socket_info| SocketInfo {
43            associated_pids: pids_by_inode
44                .remove(&socket_info.inode)
45                .unwrap_or_default()
46                .iter()
47                .map(|x| *x)
48                .collect(),
49            ..socket_info
50        })
51    })
52}