mirror of https://github.com/ospab/ostp.git
196 lines
6.4 KiB
Rust
196 lines
6.4 KiB
Rust
#[cfg(target_os = "windows")]
|
|
pub fn get_process_name_from_port(port: u16) -> Option<String> {
|
|
use winapi::shared::minwindef::ULONG;
|
|
use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER;
|
|
use winapi::um::iphlpapi::GetExtendedTcpTable;
|
|
use winapi::shared::tcpmib::{MIB_TCPTABLE_OWNER_PID, MIB_TCPROW_OWNER_PID};
|
|
|
|
let mut size: ULONG = 0;
|
|
let table_class = 5; // TCP_TABLE_OWNER_PID_ALL
|
|
let mut table = vec![0u8; 1024];
|
|
|
|
unsafe {
|
|
let mut ret = GetExtendedTcpTable(
|
|
table.as_mut_ptr() as *mut _,
|
|
&mut size,
|
|
0,
|
|
2, // AF_INET
|
|
table_class,
|
|
0,
|
|
);
|
|
|
|
if ret == ERROR_INSUFFICIENT_BUFFER {
|
|
table.resize(size as usize, 0);
|
|
ret = GetExtendedTcpTable(
|
|
table.as_mut_ptr() as *mut _,
|
|
&mut size,
|
|
0,
|
|
2, // AF_INET
|
|
table_class,
|
|
0,
|
|
);
|
|
}
|
|
|
|
if ret == 0 {
|
|
let tcp_table = &*(table.as_ptr() as *const MIB_TCPTABLE_OWNER_PID);
|
|
let row_ptr = &tcp_table.table[0] as *const MIB_TCPROW_OWNER_PID;
|
|
for i in 0..tcp_table.dwNumEntries {
|
|
let row = &*row_ptr.add(i as usize);
|
|
// Local port is in network byte order
|
|
let local_port = u16::from_be(row.dwLocalPort as u16);
|
|
if local_port == port {
|
|
return get_process_name_from_pid(row.dwOwningPid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
pub fn get_process_name_from_port_udp(port: u16) -> Option<String> {
|
|
use winapi::shared::minwindef::ULONG;
|
|
use winapi::shared::winerror::ERROR_INSUFFICIENT_BUFFER;
|
|
use winapi::um::iphlpapi::GetExtendedUdpTable;
|
|
use winapi::shared::udpmib::{MIB_UDPTABLE_OWNER_PID, MIB_UDPROW_OWNER_PID};
|
|
|
|
let mut size: ULONG = 0;
|
|
let table_class = 1; // UDP_TABLE_OWNER_PID
|
|
let mut table = vec![0u8; 1024];
|
|
|
|
unsafe {
|
|
let mut ret = GetExtendedUdpTable(
|
|
table.as_mut_ptr() as *mut _,
|
|
&mut size,
|
|
0,
|
|
2, // AF_INET
|
|
table_class,
|
|
0,
|
|
);
|
|
|
|
if ret == ERROR_INSUFFICIENT_BUFFER {
|
|
table.resize(size as usize, 0);
|
|
ret = GetExtendedUdpTable(
|
|
table.as_mut_ptr() as *mut _,
|
|
&mut size,
|
|
0,
|
|
2, // AF_INET
|
|
table_class,
|
|
0,
|
|
);
|
|
}
|
|
|
|
if ret == 0 {
|
|
let udp_table = &*(table.as_ptr() as *const MIB_UDPTABLE_OWNER_PID);
|
|
let row_ptr = &udp_table.table[0] as *const MIB_UDPROW_OWNER_PID;
|
|
for i in 0..udp_table.dwNumEntries {
|
|
let row = &*row_ptr.add(i as usize);
|
|
let local_port = u16::from_be(row.dwLocalPort as u16);
|
|
if local_port == port {
|
|
return get_process_name_from_pid(row.dwOwningPid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
fn get_process_name_from_pid(pid: u32) -> Option<String> {
|
|
use winapi::um::processthreadsapi::OpenProcess;
|
|
use winapi::um::psapi::GetModuleBaseNameW;
|
|
use winapi::um::winnt::{PROCESS_QUERY_INFORMATION, PROCESS_VM_READ};
|
|
use winapi::um::handleapi::CloseHandle;
|
|
use std::os::windows::ffi::OsStringExt;
|
|
|
|
unsafe {
|
|
let handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid);
|
|
if handle.is_null() {
|
|
return None;
|
|
}
|
|
|
|
let mut buffer = [0u16; 1024];
|
|
let len = GetModuleBaseNameW(handle, std::ptr::null_mut(), buffer.as_mut_ptr(), buffer.len() as u32);
|
|
CloseHandle(handle);
|
|
|
|
if len > 0 {
|
|
let name = std::ffi::OsString::from_wide(&buffer[..len as usize]);
|
|
return Some(name.to_string_lossy().into_owned());
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
pub fn get_process_name_from_port(port: u16) -> Option<String> {
|
|
use std::fs;
|
|
use std::io::{BufRead, BufReader};
|
|
|
|
let mut target_inode = None;
|
|
let hex_port = format!("{:04X}", port);
|
|
|
|
let check_net_file = |path: &str| -> Option<u64> {
|
|
let file = fs::File::open(path).ok()?;
|
|
let reader = BufReader::new(file);
|
|
for line in reader.lines().skip(1).filter_map(Result::ok) {
|
|
let parts: Vec<&str> = line.split_whitespace().collect();
|
|
if parts.len() >= 10 {
|
|
let local_addr = parts[1];
|
|
if local_addr.ends_with(&format!(":{}", hex_port)) {
|
|
if let Ok(inode) = parts[9].parse::<u64>() {
|
|
return Some(inode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
None
|
|
};
|
|
|
|
target_inode = check_net_file("/proc/net/tcp")
|
|
.or_else(|| check_net_file("/proc/net/tcp6"))
|
|
.or_else(|| check_net_file("/proc/net/udp"))
|
|
.or_else(|| check_net_file("/proc/net/udp6"));
|
|
|
|
let target_inode = target_inode?;
|
|
let socket_str = format!("socket:[{}]", target_inode);
|
|
|
|
for entry in fs::read_dir("/proc").ok()?.filter_map(Result::ok) {
|
|
let file_name = entry.file_name();
|
|
let pid_str = file_name.to_string_lossy();
|
|
if !pid_str.chars().all(char::is_numeric) {
|
|
continue;
|
|
}
|
|
|
|
let fd_dir = entry.path().join("fd");
|
|
if let Ok(fd_entries) = fs::read_dir(fd_dir) {
|
|
for fd_entry in fd_entries.filter_map(Result::ok) {
|
|
if let Ok(target) = fs::read_link(fd_entry.path()) {
|
|
if target.to_string_lossy() == socket_str {
|
|
let exe_path = entry.path().join("exe");
|
|
if let Ok(exe_link) = fs::read_link(exe_path) {
|
|
if let Some(name) = exe_link.file_name() {
|
|
return Some(name.to_string_lossy().into_owned());
|
|
}
|
|
}
|
|
if let Ok(comm) = fs::read_to_string(entry.path().join("comm")) {
|
|
return Some(comm.trim().to_string());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
|
|
pub fn get_process_name_from_port(_port: u16) -> Option<String> {
|
|
None
|
|
}
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
|
pub fn get_process_name_from_port_udp(port: u16) -> Option<String> {
|
|
get_process_name_from_port(port)
|
|
}
|