From 971f152a2dc0c72f35a59244d6756f4919d23e48 Mon Sep 17 00:00:00 2001 From: mux Date: Wed, 6 Aug 2025 08:48:18 +0200 Subject: [PATCH] besser spaet als nie --- .gitignore | 21 +++++ Cargo.lock | 54 +++++++++++ Cargo.toml | 9 ++ src/Socket.rs | 175 +++++++++++++++++++++++++++++++++++ src/main.rs | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 506 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/Socket.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52b9d6a --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Generated by Cargo +# will have compiled files and executables +debug +target + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# Generated by cargo mutants +# Contains mutation testing data +**/mutants.out*/ + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4d702bc --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,54 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "db" +version = "0.1.0" +dependencies = [ + "regex", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2b7f6fc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "db" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +regex = "1.11.1" diff --git a/src/Socket.rs b/src/Socket.rs new file mode 100644 index 0000000..456f3c2 --- /dev/null +++ b/src/Socket.rs @@ -0,0 +1,175 @@ + +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)] + enum SocketState{ + Listening, + Established, + Closed + } + + #[derive(PartialEq)] + struct Socket { + peer_loc: Peer, + peer_rem: Peer, + pids: Vec, + state : SocketState, + user : String, + group : String, + inode : u64 + } + impl Socket { + pub fn new(ip_loc: String, port_loc: usize, ip_rem: String, port_rem: usize, pids : Vec, state : SocketState, user : String, group : String, inode : u64) -> Socket { + Socket { + peer_loc: Peer { + ip_address: ip_loc, + port: port_loc, + }, + peer_rem: Peer { + ip_address: ip_rem, + port: port_rem, + }, + pids : pids, + state : state, + user : user, + group : group, + 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 (socket : Socket) -> String { + let mut ret_str = String::from(""); + ret_str.push_str(&socket.peer_loc.ip_address); + ret_str.push(':'); + let loc_port_str = socket.peer_loc.port.clone().to_string(); + ret_str.push_str(if socket.peer_loc.port == 0 { "*" } else { &loc_port_str }); + ret_str.push(' '); + ret_str.push_str(&socket.peer_rem.ip_address); + ret_str.push(':'); + let rem_port_str = socket.peer_rem.port.clone().to_string(); + ret_str.push_str(if socket.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 + } + + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4425e51 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,247 @@ +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, +//} + +mod Socket; + +//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)] +//enum SocketState{ +// Listening, +// Established, +// Closed +//} +// +//#[derive(PartialEq)] +//struct Socket { +// peer_loc: Peer, +// peer_rem: Peer, +// pids: Vec, +// state : SocketState, +// user : String, +// group : String, +// inode : u64 +//} +// +//impl Socket { +// pub fn new(ip_loc: String, port_loc: usize, ip_rem: String, port_rem: usize, pids : Vec, state : SocketState, user : String, group : String, inode : u64) -> Socket { +// Socket { +// peer_loc: Peer { +// ip_address: ip_loc, +// port: port_loc, +// }, +// peer_rem: Peer { +// ip_address: ip_rem, +// port: port_rem, +// }, +// pids : pids, +// state : state, +// user : user, +// group : group, +// 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); +// } +// +//// fn get_unique_inodes() -> HashSet { +//// let mut unique_inodes = HashSet::new(); +//// let pattern = Regex::new(r"^[1-4]?[0-9]{1,6}$").expect("kannst kein regex??"); +//// let dirs = fs::read_dir("/proc").expect("Cannot access /proc"); +//// for dir in dirs{ +//// match dir { +//// Ok(dir) => { +//// if !pattern.is_match( +//// &dir.file_name() +//// .into_string() +//// .expect("Dateiname ist kein gueltiger Unicode-String")[..], +//// ) { +//// continue; +//// } +//// +//// if !unique_inodes.contains(&inode){ +//// println!("{}", &inode); +//// unique_inodes.insert(inode); +//// } +//// else{ +//// continue; +//// } +//// }, +//// Err(_) => continue, +//// }; +//// } +//// unique_inodes +//// } +// +// pub fn to_string (socket : Socket) -> String { +// let mut ret_str = String::from(""); +// ret_str.push_str(&socket.peer_loc.ip_address); +// ret_str.push(':'); +// let loc_port_str = socket.peer_loc.port.clone().to_string(); +// ret_str.push_str(if socket.peer_loc.port == 0 { "*" } else { &loc_port_str }); +// ret_str.push(' '); +// ret_str.push_str(&socket.peer_rem.ip_address); +// ret_str.push(':'); +// let rem_port_str = socket.peer_rem.port.clone().to_string(); +// ret_str.push_str(if socket.peer_rem.port == 0 { "*" } else { &rem_port_str }); +// ret_str.push('\n'); +// return ret_str; +// } +// +//// fn convert_line(line : String) -> HashSet{ +//// let mut sockets : HashSet; +//// let line_vec = line.split_whitespace().collect::>(); +//// conv_str.push_str(&Peer::convert_ip_hex_dec(line_vec[1].split(":").nth(0).unwrap())); +//// conv_str.push_str(":"); +//// let loc_port = Peer::convert_port_hex_dec(line_vec[1].split(":").nth(1).expect("gehtnd3")); +//// let loc_port_str = loc_port.clone().to_string(); +//// conv_str.push_str(if loc_port == 0 { "*" } else { &loc_port_str } ); +//// conv_str.push_str(" "); +//// conv_str.push_str(&Peer::convert_ip_hex_dec(line_vec[2].split(":").nth(0).expect("gehtnd2"))); +//// conv_str.push_str(":"); +//// let loc_port = Peer::convert_port_hex_dec(line_vec[2].split(":").nth(1).expect("gehtnd3")); +//// let loc_port_str = loc_port.clone().to_string(); +//// conv_str.push_str(if loc_port == 0 { "*" } else { &loc_port_str } ); +//// conv_str.push('\n'); +//// return conv_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 +// } +// +// fn get_pids (complete_file : String) -> Vec{ +// return Vec::::new(); +// } +//} + +fn get_index(line: String, index: usize) -> String { + line.split_whitespace().nth(index).expect("upsi").to_owned() +} + +//fn get_local_addresses_and_ports(proc_string : &mut String){ +// let local_addresses : Vec = Vec::new(); +// let tcp_file : String = get_socket_info(); +// tcp.lines(). +// println!("{:?}", local_addresses); +//} + +//fn get_local_port(){ +// proc_string.lines().for_each( |x| { +// local_addresses.push(i64::from_str_radix(&get_index_and_convert_to_dec(x.to_owned(), 2), 16)) +// }); +//} +fn get_remote_address() {} +fn get_remote_port() {} + +fn main() { +// let complete_file = Socket::get_all_unique_socket_infos(); +}