use regex::Regex; use std::collections::HashSet; use std::fmt::{Display, Formatter, Write}; use std::{fmt, fs}; use std::fs::{read_to_string, ReadDir}; use std::path::PathBuf; use crate::socket::socket::{pids_to_string, Id, Tcp_Socket}; type inode = u64; type pid = u64; type pids = HashSet; mod socket; fn get_socket_inodes_by_pid(pid : u64, socket_patt : &Regex) -> HashSet { let mut inodes = HashSet::::new(); let mut path = String::from("/proc/"); path.push_str(&pid.to_string()); path.push_str("/fd/"); let mut contents: ReadDir; match fs::read_dir(path) { Ok(dir) => { contents = dir; }, Err(_) => return HashSet::::new() }; for fd in contents { match fd { Ok(fd) => { let path_name = fs::read_link(fd.path()); let mut name : PathBuf; match path_name { Ok(link) => name = link, Err(_) => continue, } let name2 = name.file_name().unwrap().to_str().unwrap(); if socket_patt.is_match(name2) { inodes.insert(socket_patt.captures(name2).unwrap().get(1).unwrap().as_str().parse::().unwrap()); } }, Err(_) => continue, } } inodes } fn get_socket_by_inode(sockets : &HashSet, inode : u64) -> Option { sockets.clone().iter().map(|x| x.to_owned()).find(|x|x.inode == inode) } fn get_tcp_file_by_pid(pid_pattern : &Regex, pid: pid) -> String { let mut path = String::from("/proc/"); path.push_str(&pid.to_string()); path.push_str("/net/tcp"); fs::read_to_string(path).unwrap().lines().skip(1).map(|x| x.to_owned()).collect::>().join("\n") } fn parse_tcp_file_line(line : String) -> socket::socket::Tcp_Socket { socket::socket::Tcp_Socket::new(socket::socket::Peer::build_from_hex(&get_index(&line.clone(),1)), socket::socket::Peer::build_from_hex(&get_index(&line.clone(),2)), HashSet::::new(), socket::socket::Tcp_SocketState::new(socket::socket::Peer::convert_port_hex_dec(&get_index(&line.clone(), 3))), socket::socket::Id::create_def(), socket::socket::Id::create_def(), get_index(&line, 9).parse().unwrap()) } fn get_readable_proc_pids(pid_pattern : &Regex) -> Vec { let mut pids = Vec::::new(); let dirs = fs::read_dir("/proc/").expect("proc kann nicht gelesen werden, Berechtigung?"); for dir in dirs { match dir { Ok(dir) => { let name = dir.file_name().into_string().unwrap(); if !pid_pattern.is_match(&name) { continue; } pids.push(name.parse().unwrap()) }, Err(_) => continue }; } pids } fn get_uid_guid_by_pid(pid : pid) -> (socket::socket::Id,socket::socket::Id) { let mut uid : Id; let mut gid : Id; let mut status_path = String::from("/proc/"); status_path.push_str(&pid.to_string()); status_path.push_str("/status"); let status_file = fs::read_to_string(status_path).unwrap(); let mut iter = status_file.lines(); let uid_str = iter.find(|x| x.starts_with("Uid:")).unwrap().to_owned(); let gid_str = iter.find(|x| x.starts_with("Gid:")).unwrap().to_owned(); (Id::new(get_index(&uid_str.clone(), 1).parse().unwrap(), get_index(&uid_str.clone(), 2).parse().unwrap(), get_index(&uid_str.clone(), 3).parse().unwrap(), get_index(&uid_str, 4).parse().unwrap()), Id::new(get_index(&gid_str.clone(), 1).parse().unwrap(), get_index(&gid_str.clone(), 2).parse().unwrap(), get_index(&gid_str.clone(), 3).parse().unwrap(), get_index(&gid_str, 4).parse().unwrap())) } fn add_pid_to_tcp_sockets(sockets : &mut Vec, inodes : HashSet, pid : pid) -> (){ let s2 = sockets.clone(); for (i, v) in s2.iter().enumerate(){ if inodes.contains(&v.inode) { sockets.get_mut(i).unwrap().pids.insert(pid); } } } pub fn format_output(combination : socket::socket::Combination, sockets : &Vec) -> String{ let header_loc_ip = "Local Address"; let header_loc_port = "Port"; let header_rem_ip = "Remote Address"; let header_state = "State"; let header_rem_port = header_loc_port; let header_uid_real = "real-uid"; let header_uid_eff = "effective-uid"; let header_gid_real = "real-gid"; let header_gid_eff = "effective-gid"; let header_pids = "PIDs"; let mut ret_str = String::from(""); let mut max_loc_ip_len = header_loc_ip.len(); let mut max_loc_port_len = header_loc_port.len(); let mut max_rem_ip_len = header_rem_ip.len(); let mut max_rem_port_len = max_loc_port_len; let mut max_state_len = header_state.len(); let mut max_real_uid_len = header_uid_real.len(); let mut max_eff_uid_len = header_uid_eff.len(); let mut max_real_gid_len = header_gid_real.len(); let mut max_eff_gid_len = header_gid_eff.len(); let mut max_pids_len = header_pids.len(); sockets.clone().iter().for_each(|x| { let curr_loc_ip_len = x.get_loc_ip_string().len(); let curr_loc_port_len = x.get_loc_port_string().len(); let curr_rem_ip_len = x.get_rem_ip_string().len(); let curr_rem_port_len = x.get_rem_port_string().len(); let curr_state_len = x.get_state().to_string().len(); let (curr_real_uid,curr_eff_uid) = x.get_real_eff_uid_string(); let curr_real_uid_len = curr_real_uid.len(); let curr_eff_uid_len = curr_eff_uid.len(); let (curr_real_gid, curr_eff_gid) = x.get_real_eff_gid_String(); let curr_real_gid_len = curr_real_gid.len(); let curr_eff_gid_len = curr_eff_gid.len(); let curr_pids_len = pids_to_string(&x.pids).len(); max_loc_ip_len = if (curr_loc_ip_len > max_loc_ip_len) { curr_loc_ip_len } else { max_loc_ip_len }; max_loc_port_len = if (curr_loc_port_len > max_loc_port_len) { curr_loc_port_len } else { max_loc_port_len }; max_rem_ip_len = if (curr_rem_ip_len > max_rem_ip_len) { curr_rem_ip_len } else { max_rem_ip_len }; max_rem_port_len = if (curr_rem_port_len > max_rem_port_len) { curr_rem_port_len } else { max_rem_port_len }; max_state_len = if(curr_state_len > max_state_len) { curr_state_len } else { max_state_len }; if combination == socket::socket::Combination::tnap{ max_real_uid_len = if (curr_real_uid_len > max_real_uid_len) { curr_real_uid_len } else { max_real_uid_len }; max_eff_uid_len = if (curr_eff_uid_len > max_eff_uid_len) { curr_eff_uid_len } else { max_eff_uid_len }; max_real_gid_len = if (curr_real_gid_len > max_real_gid_len) { curr_real_gid_len } else { max_real_gid_len }; max_eff_gid_len = if (curr_eff_gid_len > max_eff_gid_len) { curr_eff_gid_len } else { max_eff_gid_len }; max_pids_len = if (curr_pids_len > max_pids_len) { curr_pids_len } else { max_pids_len }; } }); max_loc_ip_len = max_loc_ip_len + 3; max_rem_ip_len = max_rem_ip_len + 3; max_real_uid_len = max_real_uid_len + 3; max_real_gid_len = max_real_gid_len + 3; max_pids_len = max_pids_len + 3; match combination { socket::socket::Combination::tna => { ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:max_rem_ip_len$}:{:max_state_len$} {:>max_loc_ip_len$}:{:max_rem_ip_len$}:{: { ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:max_rem_ip_len$}:{:max_real_uid_len$}|{:max_real_gid_len$}|{:max_pids_len$}\n", header_state , header_loc_ip , header_loc_port, header_rem_ip,header_rem_port, header_uid_real, header_uid_eff, header_gid_real, header_gid_eff, header_pids )); sockets.clone().iter().for_each(|x| { let (real_uid, eff_uid) = x.get_real_eff_uid_string(); let (real_gid,eff_gid) = x.get_real_eff_gid_String(); ret_str.push_str(&format!("{:>max_state_len$} {:>max_loc_ip_len$}:{:max_rem_ip_len$}:{:max_real_uid_len$}|{:max_real_gid_len$}|{:max_pids_len$}\n", x.get_state().to_string(), x.get_loc_ip_string(), x.get_loc_port_string(), x.get_rem_ip_string(), x.get_rem_port_string(), real_uid, eff_uid , real_gid , eff_gid, pids_to_string(&x.pids))) }); } } ret_str } fn get_all_tcp_sockets(pid_pattern : &Regex, socket_patt : &Regex) -> Vec { let mut sockets = Vec::::new(); let pids = get_readable_proc_pids(pid_pattern); let mut inodes = HashSet::::new(); pids.iter().for_each(|x| { get_tcp_file_by_pid(&pid_pattern.clone(), *x).lines().for_each(|y| { add_to_tcp_sockets(&mut sockets, parse_tcp_file_line(y.to_owned())); }); inodes = get_socket_inodes_by_pid(*x, socket_patt); let (uid, gid) = get_uid_guid_by_pid(*x); for (i, v) in sockets.clone().iter().enumerate() { if inodes.contains(&v.inode){ add_pid_to_tcp_sockets(&mut sockets, inodes.clone(), *x); } Tcp_Socket::add_uid_gid(sockets.get_mut(i).unwrap(),uid, gid); } }); sockets } fn add_to_tcp_sockets(sockets : &mut Vec, socket: socket::socket::Tcp_Socket) -> (){ if !sockets.contains(&socket) { sockets.push(socket); } } fn get_socket_info() -> Vec { let mut sockets = Vec::::new(); sockets } fn get_index(line: &String, index: usize) -> String { line.clone().split_whitespace().nth(index).expect("upsi").to_owned() } fn get_remote_address() {} fn get_remote_port() {} fn main() { let socket_patt : Regex = Regex::new(r"socket:\[([0-9]+)\]").expect("kannst kein regex?? xd"); let pid_pattern = Regex::new(r"^[1-4]?[0-9]{1,6}$").expect("kannst kein regex??"); let sockets = get_all_tcp_sockets(&pid_pattern, &socket_patt); println!("{}", format_output(socket::socket::Combination::tnap, &sockets)); }