From cda63885964269343290a4602a3f24f435128a43 Mon Sep 17 00:00:00 2001 From: Andrew Rioux Date: Sat, 2 Sep 2023 16:58:25 -0400 Subject: [PATCH] feat: fleshed out handling a new connection --- Makefile.toml | 2 +- pcap-sys/src/lib.rs | 6 +- .../sparse-05-server/src/capabilities.rs | 10 ++- sparse-05/sparse-05-server/src/connection.rs | 16 ++++- sparse-05/sparse-05-server/src/interface.rs | 10 +-- sparse-05/sparse-05-server/src/main.rs | 61 ++++++++++++++++--- 6 files changed, 81 insertions(+), 24 deletions(-) diff --git a/Makefile.toml b/Makefile.toml index 2efd1b2..9140707 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -37,7 +37,7 @@ args = ["clean"] workspace = false command = "docker-compose" args = ["run", "build", "check", "${@}"] -watch = { watch = ["nl-sys/src", "pcap-sys/src"] } +watch = { watch = ["nl-sys/src", "pcap-sys/src", "sparse-05/sparse-05-client/src", "sparse-05/sparse-05-common/src", "sparse-05/sparse-05-server/src"] } #----------------------- # diff --git a/pcap-sys/src/lib.rs b/pcap-sys/src/lib.rs index 97709ce..d1110d4 100644 --- a/pcap-sys/src/lib.rs +++ b/pcap-sys/src/lib.rs @@ -328,7 +328,7 @@ impl Interface { struct ListenHandler<'a, F> where - F: Fn(&Interface, packets::EthernetPkt) -> error::Result, + F: FnMut(&Interface, packets::EthernetPkt) -> error::Result, { packet_handler: F, break_on_fail: bool, @@ -344,14 +344,14 @@ impl Interface { packet_count: i32, ) -> (Option, i32) where - F: Fn(&Interface, packets::EthernetPkt) -> error::Result, + F: FnMut(&Interface, packets::EthernetPkt) -> error::Result, { unsafe extern "C" fn cback( user: *mut libc::c_void, header: *const ffi::PktHeader, data: *const u8, ) where - F: Fn(&Interface, packets::EthernetPkt) -> error::Result, + F: FnMut(&Interface, packets::EthernetPkt) -> error::Result, { let info = &mut *(user as *mut ListenHandler); diff --git a/sparse-05/sparse-05-server/src/capabilities.rs b/sparse-05/sparse-05-server/src/capabilities.rs index 2f09161..f729a66 100644 --- a/sparse-05/sparse-05-server/src/capabilities.rs +++ b/sparse-05/sparse-05-server/src/capabilities.rs @@ -4,7 +4,7 @@ use sparse_05_common::messages::{Capabilities, TransportType}; const CAP_SETUID: u32 = 1 << 7; const CAP_NET_RAW: u32 = 1 << 13; -const SYS_capget: i64 = 125; +const SYS_CAPGET: i64 = 125; #[allow(non_camel_case_types)] #[repr(C)] @@ -41,7 +41,7 @@ fn get_username(uid: u32) -> anyhow::Result> { })) } -pub fn get_capabilities() -> anyhow::Result { +fn get_current_capabilities() -> anyhow::Result { let mut header = cap_user_header_t { version: 0x20080522, pid: 0, @@ -52,7 +52,7 @@ pub fn get_capabilities() -> anyhow::Result { inheritable: 0, }; let oscapabilities = - unsafe { libc::syscall(SYS_capget, &mut header as *const _, &mut data as *mut _) }; + unsafe { libc::syscall(SYS_CAPGET, &mut header as *const _, &mut data as *mut _) }; if oscapabilities == -1 { return Err(std::io::Error::last_os_error())?; @@ -79,3 +79,7 @@ pub fn get_capabilities() -> anyhow::Result { transport, }) } + +pub fn get_capabilities() -> anyhow::Result { + get_current_capabilities() +} diff --git a/sparse-05/sparse-05-server/src/connection.rs b/sparse-05/sparse-05-server/src/connection.rs index 44bdc2a..53c06fc 100644 --- a/sparse-05/sparse-05-server/src/connection.rs +++ b/sparse-05/sparse-05-server/src/connection.rs @@ -1,10 +1,22 @@ -use std::sync::mpsc::Sender; +use std::{net::Ipv4Addr, sync::mpsc::Sender}; use pcap_sys::packets::EthernetPacket; #[derive(Clone)] pub struct ConnectionHandle {} -pub fn spawn_connection_handler(packet_sender: Sender) -> ConnectionHandle { +impl ConnectionHandle { + pub fn handle_packet(&self, packet: EthernetPacket) -> anyhow::Result<()> { + Ok(()) + } +} + +pub enum State {} + +pub fn spawn_connection_handler( + packet_sender: Sender, + connection_packet: EthernetPacket, + connection_killer: Sender<(Ipv4Addr, u16)>, +) -> ConnectionHandle { ConnectionHandle {} } diff --git a/sparse-05/sparse-05-server/src/interface.rs b/sparse-05/sparse-05-server/src/interface.rs index 4488d22..11267a5 100644 --- a/sparse-05/sparse-05-server/src/interface.rs +++ b/sparse-05/sparse-05-server/src/interface.rs @@ -22,7 +22,7 @@ impl Interface { .find(|eth| eth.starts_with("eth") || eth.starts_with("en")) .ok_or(anyhow!("could not get an ethernet interface"))?; - let mut interface = loop { + let interface = loop { macro_rules! retry { ($e:expr) => {{ match $e { @@ -118,14 +118,14 @@ pub enum InterfaceReceiver { } impl InterfaceReceiver { - pub fn listen(&self, f: F) -> anyhow::Result<()> + pub fn listen(&self, mut f: F) -> anyhow::Result<()> where - F: Fn(packets::EthernetPacket) -> anyhow::Result<()>, + F: FnMut(packets::EthernetPacket) -> anyhow::Result<()>, { match self { Self::RawUdp(interf) => interf.listen( move |_, packet| { - (f)(packet.to_owned()); + let _ = (f)(packet.to_owned()); Ok(false) }, false, @@ -153,7 +153,7 @@ impl InterfaceReceiver { &Layer3Packet::IPv4(ip_packet), ); - (f)(ether_packet); + let _ = (f)(ether_packet); }, }; diff --git a/sparse-05/sparse-05-server/src/main.rs b/sparse-05/sparse-05-server/src/main.rs index 70edd0b..a12a4d7 100644 --- a/sparse-05/sparse-05-server/src/main.rs +++ b/sparse-05/sparse-05-server/src/main.rs @@ -1,17 +1,19 @@ use std::{ collections::HashMap, net::Ipv4Addr, - sync::{mpsc::channel, Arc}, + sync::{mpsc::channel, Arc, Mutex}, thread, }; -use anyhow::{anyhow, bail, Context}; +use anyhow::{bail, Context}; use connection::ConnectionHandle; use ed25519_dalek::PublicKey; use pcap_sys::packets::EthernetPacket; use sparse_05_common::CONFIG_SEPARATOR; +use crate::connection::spawn_connection_handler; + mod capabilities; mod connection; mod interface; @@ -40,17 +42,56 @@ fn main() -> anyhow::Result<()> { let interface = interface::Interface::new(capabilities.transport, port)?; let (interface_sender, interface_receiver) = interface.split()?; - let mut connections: HashMap<(Ipv4Addr, u16), ConnectionHandle> = HashMap::new(); + let connections: Arc>> = + Arc::new(Mutex::new(HashMap::new())); let (send_eth_packet, recv_eth_packet) = channel::(); + let (kill_connection, kill_connection_recv) = channel::<(Ipv4Addr, u16)>(); - { - thread::spawn(move || loop { - let Ok(packet) = recv_eth_packet.recv() else { continue }; - if let Err(_) = interface_sender.sendpacket(packet.pkt()) {} - }); - } + thread::spawn(move || loop { + let Ok(packet) = recv_eth_packet.recv() else { continue }; + if let Err(_) = interface_sender.sendpacket(packet.pkt()) {} + }); - interface_receiver.listen(move |_| Ok(()))?; + thread::spawn({ + let connections = Arc::clone(&connections); + move || loop { + let Ok(connection) = kill_connection_recv.recv() else { continue }; + if let Ok(mut e) = connections.lock() { + e.remove(&connection); + } + } + }); + + interface_receiver.listen(|pkt| { + use pcap_sys::packets::*; + + let pkt = pkt.pkt(); + + let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + + let connection_handle = &(ip_pkt.dest_ip(), udp_pkt.srcport()); + + if let Ok(mut connections) = connections.lock() { + let connection = connections.get(connection_handle); + + match connection { + None => { + let new_connection = spawn_connection_handler( + send_eth_packet.clone(), + pkt.to_owned(), + kill_connection.clone(), + ); + connections.insert(*connection_handle, new_connection); + } + Some(conn) => { + conn.handle_packet(pkt.to_owned())?; + } + } + } + + Ok(()) + })?; Ok(()) }