summaryrefslogtreecommitdiffstats
path: root/src/os/linux.rs
blob: 7ac5e9f6d9a2ac6fcef4bc4fa0692736130e9bc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use ::pnet::datalink::Channel::Ethernet;
use ::pnet::datalink::DataLinkReceiver;
use ::pnet::datalink::{self, NetworkInterface, Config};
use ::std::io::stdin;
use ::termion::event::Event;
use ::termion::input::TermRead;

use ::std::collections::HashMap;
use ::std::net::IpAddr;
use ::std::sync::Arc;
use ::std::time;

use ::std::sync::atomic::AtomicBool;

use ::signal_hook;

use ::procfs::FDTarget;

use crate::network::{Connection, Protocol};

pub struct KeyboardEvents;

impl Iterator for KeyboardEvents {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        match stdin().events().next() {
            Some(Ok(ev)) => Some(ev),
            _ => None,
        }
    }
}

pub fn get_datalink_channel(interface: &NetworkInterface) -> Box<DataLinkReceiver> {
    let mut config = Config::default();
    config.read_timeout = Some(time::Duration::new(0, 0));
    match datalink::channel(interface, config) {
        Ok(Ethernet(_tx, rx)) => rx,
        Ok(_) => panic!("Unhandled channel type"),
        Err(e) => panic!(
            "An error occurred when creating the datalink channel: {}",
            e
        ),
    }
}

pub fn get_interface(interface_name: &str) -> Option<NetworkInterface> {
    datalink::interfaces()
        .into_iter()
        .find(|iface| iface.name == interface_name)
}

pub fn get_open_sockets() -> HashMap<Connection, String> {
    let mut open_sockets = HashMap::new(); // TODO: better
    let all_procs = procfs::all_processes();

    let mut inode_to_procname = HashMap::new();
    for process in all_procs {
        if let Ok(fds) = process.fd() {
            let procname = process.stat.comm;
            for fd in fds {
                if let FDTarget::Socket(inode) = fd.target {
                    inode_to_procname.insert(inode, procname.clone());
                }
            }
        }
    }

    let tcp = ::procfs::tcp().unwrap();
    for entry in tcp.into_iter() {
        if let (Some(connection), Some(procname)) = (
            Connection::new(entry.local_address, entry.remote_address, Protocol::Tcp),
            inode_to_procname.get(&entry.inode),
        ) {
            open_sockets.insert(connection, procname.clone());
        };
    }

    let udp = ::procfs::udp().unwrap();
    for entry in udp.into_iter() {
        if let (Some(connection), Some(procname)) = (
            Connection::new(entry.local_address, entry.remote_address, Protocol::Udp),
            inode_to_procname.get(&entry.inode),
        ) {
            open_sockets.insert(connection, procname.clone());
        };
    }
    open_sockets
}

pub fn lookup_addr(ip: &IpAddr) -> Option<String> {
    ::dns_lookup::lookup_addr(ip).ok()
}

pub fn receive_winch(winch: &Arc<AtomicBool>) {
    ::signal_hook::flag::register(
        signal_hook::SIGWINCH, winch.clone()
    ).expect("Failed to register SIGWINCH");
}