diff --git a/src/.socket.rs.swp b/src/.socket.rs.swp new file mode 100644 index 0000000..7c9de9c Binary files /dev/null and b/src/.socket.rs.swp differ diff --git a/src/socket.rs b/src/socket.rs new file mode 100644 index 0000000..e5500c4 --- /dev/null +++ b/src/socket.rs @@ -0,0 +1,212 @@ + +mod Socket { + + use regex::Regex; + use std::collections::HashSet; + use std::fs; + use std::fs::read_to_string; + use std::os::unix::fs::MetadataExt; + + #[derive(PartialEq)] + struct Peer { + ip_address: String, + port: usize, + } + + impl Peer { + fn new() -> Peer { + Peer { + ip_address: "0.0.0.0".to_string(), + port: 0, + } + } + + fn build_from_hex(hex_ip: &str, hex_port: &str) -> Peer { + Peer { + ip_address: Self::convert_ip_hex_dec(hex_ip), + port: Self::convert_port_hex_dec(hex_port), + } + } + + fn convert_ip_hex_dec(ip_address: &str) -> String { + let mut buffer: String = String::new(); + let mut ip_quads: Vec = vec![]; + for (i, v) in ip_address.chars().enumerate() { + if i % 2 == 1 { + buffer.push(v); + ip_quads.push( + u64::from_str_radix(&buffer, 16) + .expect("upsi 2") + .to_string(), + ); + buffer = String::new(); + } else { + buffer.push(v); + } + } + ip_quads + .iter() + .rev() + .map(|x| x.to_owned()) + .collect::>() + .join(".") + } + + fn convert_port_hex_dec(port: &str) -> usize { + usize::from_str_radix(port, 16).expect("upsi 3") + } + } + + #[derive(PartialEq)] + pub enum SocketState{ + Listening, + Established, + Closed + } + + #[derive(PartialEq)] + pub struct Socket { + peer_loc: Peer, + peer_rem: Peer, + pids: Vec, + state : SocketState, + user : String, + group : String, + inode : u64 + } + + impl Clone for Socket { + fn clone(&self) -> Self { + Self { + peer_loc : self.peer_loc.clone(), + peer_rem : self.peer_rem .clone(), + pids : self.pids.clone(), + state : self.state.clone(), + user : self.user.clone(), + group : self.user.clone(), + inode : self.inode.clone() + } + } + } + + impl Socket { + pub fn new(ip_loc: &str, port_loc: usize, ip_rem: &str, port_rem: usize, pids : Vec, state : SocketState, user : &str, group : &str, inode : u64) -> Socket { + Socket { + peer_loc: Peer { + ip_address: ip_loc.to_string(), + port: port_loc, + }, + peer_rem: Peer { + ip_address: ip_rem.to_string(), + port: port_rem, + }, + pids : pids, + state : state, + user : user.to_string(), + group : group.to_string(), + inode : inode, + } + } + + fn get_tcp_file_inode(pid: u64) -> u64 { + let mut path = String::from("/proc/"); + path.push_str(&pid.to_string()); + path.push_str("/net/tcp"); + + let inode = fs::metadata(&path) + .expect("Cannot read metadata") + .ino(); + return inode; + } + + fn check_inode_seen(seen_inodes : &HashSet, pid : u64) -> bool { + let inode = Socket::get_tcp_file_inode(pid); + return seen_inodes.contains(&inode); + } + + fn add_inode(seen_inodes : &mut HashSet, pid: u64){ + let inode = Socket::get_tcp_file_inode(pid); + seen_inodes.insert(inode); + } + + pub fn to_string (self) -> String { + let mut ret_str = String::from(""); + ret_str.push_str(&self.peer_loc.ip_address); + ret_str.push(':'); + let loc_port_str = self.peer_loc.port.clone().to_string(); + ret_str.push_str(if self.peer_loc.port == 0 { "*" } else { &loc_port_str }); + ret_str.push(' '); + ret_str.push_str(&self.peer_rem.ip_address); + ret_str.push(':'); + let rem_port_str = self.peer_rem.port.clone().to_string(); + ret_str.push_str(if self.peer_rem.port == 0 { "*" } else { &rem_port_str }); + ret_str.push('\n'); + return ret_str; + } + + fn get_all_unique_socket_infos() -> String { + let pattern = Regex::new(r"^[1-4]?[0-9]{1,6}$").expect("kannst kein regex??"); + let contents = + fs::read_dir("/proc/").expect("upsi 4 (proc kann nicht gelesen werden, Berechtigung?)"); + let mut seen_inodes = HashSet::::new(); + let mut complete_file: String = String::new(); + for dir in contents { + match dir { + Ok(dir) => { + if !pattern.is_match( + &dir.file_name() + .into_string() + .expect("Dateiname ist kein gueltiger Unicode-String")[..], + ) { + continue; + } + let mut path = dir.path().into_os_string().into_string().expect("gehtnd"); + path.push_str("/net/tcp"); + let pid = &path.split("/").nth(2).expect("gesplittert"); + if !Socket::check_inode_seen(&seen_inodes, pid.parse::().unwrap()) { + Socket::add_inode(& mut seen_inodes, pid.parse::().unwrap()); + let test = &fs::read_to_string(path) + .expect("Could not read proc/pid/net/tcp") + .lines() + .skip(1) + // .map(|x| Socket::convert_line(x.to_string())) + .map(|x| x.to_owned()) + .collect::>() + .join("\n"); + complete_file.push_str(test); + } + else{ + continue; + } + }, + Err(_) => continue, + }; + } + // complete_file + complete_file + } + + } +} + +#[cfg(test)] +mod tests { + + use crate::socket::Socket::*; + + fn init_sockets() -> Vec { + let sockets = Vec::::new(); + sockets.push(Socket::new("93.83.160.12", 21345, "0.0.0.0", 0, Vec::::new(), Socket::SocketState::Listening, "root", "root", 123123)); + sockets.push(Socket::new("195.201.90.97", 8843, "0.0.0.0", 443, Vec::::new(), Socket::SocketState::Established, "apache", "apache", 218389)); + sockets.push(Socket::new("255.255.255.255", 193193, "0.0.0.0", 8080, Vec::::new(), Socket::SocketState::Listening, "node", "node", 1301011)); + return sockets; + } + + #[cfg(test)] + pub fn test_to_string() -> (){ + let sockets = init_sockets(); + assert_eq!("93.83.160.12:21345 0.0.0.0:*", sockets[0].clone().to_string()); + assert_eq!("195.201.90.97:8843 0.0.0.0:443", sockets[1].clone().to_string()); + assert_eq!("255.255.255.255:193193 0.0.0.0:8080", sockets[2].clone().to_string()); + } +}