feat: fleshed out handling a new connection

This commit is contained in:
Andrew Rioux 2023-09-02 16:58:25 -04:00
parent d7a0deba0c
commit cda6388596
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
6 changed files with 81 additions and 24 deletions

View File

@ -37,7 +37,7 @@ args = ["clean"]
workspace = false workspace = false
command = "docker-compose" command = "docker-compose"
args = ["run", "build", "check", "${@}"] 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"] }
#----------------------- #-----------------------
# #

View File

@ -328,7 +328,7 @@ impl<T: Activated> Interface<T> {
struct ListenHandler<'a, F> struct ListenHandler<'a, F>
where where
F: Fn(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>, F: FnMut(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>,
{ {
packet_handler: F, packet_handler: F,
break_on_fail: bool, break_on_fail: bool,
@ -344,14 +344,14 @@ impl<T: NotListening> Interface<T> {
packet_count: i32, packet_count: i32,
) -> (Option<error::Error>, i32) ) -> (Option<error::Error>, i32)
where where
F: Fn(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>, F: FnMut(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>,
{ {
unsafe extern "C" fn cback<F>( unsafe extern "C" fn cback<F>(
user: *mut libc::c_void, user: *mut libc::c_void,
header: *const ffi::PktHeader, header: *const ffi::PktHeader,
data: *const u8, data: *const u8,
) where ) where
F: Fn(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>, F: FnMut(&Interface<DevListening>, packets::EthernetPkt) -> error::Result<bool>,
{ {
let info = &mut *(user as *mut ListenHandler<F>); let info = &mut *(user as *mut ListenHandler<F>);

View File

@ -4,7 +4,7 @@ use sparse_05_common::messages::{Capabilities, TransportType};
const CAP_SETUID: u32 = 1 << 7; const CAP_SETUID: u32 = 1 << 7;
const CAP_NET_RAW: u32 = 1 << 13; const CAP_NET_RAW: u32 = 1 << 13;
const SYS_capget: i64 = 125; const SYS_CAPGET: i64 = 125;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[repr(C)] #[repr(C)]
@ -41,7 +41,7 @@ fn get_username(uid: u32) -> anyhow::Result<Option<String>> {
})) }))
} }
pub fn get_capabilities() -> anyhow::Result<Capabilities> { fn get_current_capabilities() -> anyhow::Result<Capabilities> {
let mut header = cap_user_header_t { let mut header = cap_user_header_t {
version: 0x20080522, version: 0x20080522,
pid: 0, pid: 0,
@ -52,7 +52,7 @@ pub fn get_capabilities() -> anyhow::Result<Capabilities> {
inheritable: 0, inheritable: 0,
}; };
let oscapabilities = 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 { if oscapabilities == -1 {
return Err(std::io::Error::last_os_error())?; return Err(std::io::Error::last_os_error())?;
@ -79,3 +79,7 @@ pub fn get_capabilities() -> anyhow::Result<Capabilities> {
transport, transport,
}) })
} }
pub fn get_capabilities() -> anyhow::Result<Capabilities> {
get_current_capabilities()
}

View File

@ -1,10 +1,22 @@
use std::sync::mpsc::Sender; use std::{net::Ipv4Addr, sync::mpsc::Sender};
use pcap_sys::packets::EthernetPacket; use pcap_sys::packets::EthernetPacket;
#[derive(Clone)] #[derive(Clone)]
pub struct ConnectionHandle {} pub struct ConnectionHandle {}
pub fn spawn_connection_handler(packet_sender: Sender<EthernetPacket>) -> ConnectionHandle { impl ConnectionHandle {
pub fn handle_packet(&self, packet: EthernetPacket) -> anyhow::Result<()> {
Ok(())
}
}
pub enum State {}
pub fn spawn_connection_handler(
packet_sender: Sender<EthernetPacket>,
connection_packet: EthernetPacket,
connection_killer: Sender<(Ipv4Addr, u16)>,
) -> ConnectionHandle {
ConnectionHandle {} ConnectionHandle {}
} }

View File

@ -22,7 +22,7 @@ impl Interface {
.find(|eth| eth.starts_with("eth") || eth.starts_with("en")) .find(|eth| eth.starts_with("eth") || eth.starts_with("en"))
.ok_or(anyhow!("could not get an ethernet interface"))?; .ok_or(anyhow!("could not get an ethernet interface"))?;
let mut interface = loop { let interface = loop {
macro_rules! retry { macro_rules! retry {
($e:expr) => {{ ($e:expr) => {{
match $e { match $e {
@ -118,14 +118,14 @@ pub enum InterfaceReceiver {
} }
impl InterfaceReceiver { impl InterfaceReceiver {
pub fn listen<F>(&self, f: F) -> anyhow::Result<()> pub fn listen<F>(&self, mut f: F) -> anyhow::Result<()>
where where
F: Fn(packets::EthernetPacket) -> anyhow::Result<()>, F: FnMut(packets::EthernetPacket) -> anyhow::Result<()>,
{ {
match self { match self {
Self::RawUdp(interf) => interf.listen( Self::RawUdp(interf) => interf.listen(
move |_, packet| { move |_, packet| {
(f)(packet.to_owned()); let _ = (f)(packet.to_owned());
Ok(false) Ok(false)
}, },
false, false,
@ -153,7 +153,7 @@ impl InterfaceReceiver {
&Layer3Packet::IPv4(ip_packet), &Layer3Packet::IPv4(ip_packet),
); );
(f)(ether_packet); let _ = (f)(ether_packet);
}, },
}; };

View File

@ -1,17 +1,19 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
net::Ipv4Addr, net::Ipv4Addr,
sync::{mpsc::channel, Arc}, sync::{mpsc::channel, Arc, Mutex},
thread, thread,
}; };
use anyhow::{anyhow, bail, Context}; use anyhow::{bail, Context};
use connection::ConnectionHandle; use connection::ConnectionHandle;
use ed25519_dalek::PublicKey; use ed25519_dalek::PublicKey;
use pcap_sys::packets::EthernetPacket; use pcap_sys::packets::EthernetPacket;
use sparse_05_common::CONFIG_SEPARATOR; use sparse_05_common::CONFIG_SEPARATOR;
use crate::connection::spawn_connection_handler;
mod capabilities; mod capabilities;
mod connection; mod connection;
mod interface; mod interface;
@ -40,17 +42,56 @@ fn main() -> anyhow::Result<()> {
let interface = interface::Interface::new(capabilities.transport, port)?; let interface = interface::Interface::new(capabilities.transport, port)?;
let (interface_sender, interface_receiver) = interface.split()?; let (interface_sender, interface_receiver) = interface.split()?;
let mut connections: HashMap<(Ipv4Addr, u16), ConnectionHandle> = HashMap::new(); let connections: Arc<Mutex<HashMap<(Ipv4Addr, u16), ConnectionHandle>>> =
Arc::new(Mutex::new(HashMap::new()));
let (send_eth_packet, recv_eth_packet) = channel::<EthernetPacket>(); let (send_eth_packet, recv_eth_packet) = channel::<EthernetPacket>();
let (kill_connection, kill_connection_recv) = channel::<(Ipv4Addr, u16)>();
{ thread::spawn(move || loop {
thread::spawn(move || loop { let Ok(packet) = recv_eth_packet.recv() else { continue };
let Ok(packet) = recv_eth_packet.recv() else { continue }; if let Err(_) = interface_sender.sendpacket(packet.pkt()) {}
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(()) Ok(())
} }