feat: fleshed out handling a new connection
This commit is contained in:
parent
d7a0deba0c
commit
cda6388596
@ -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"] }
|
||||||
|
|
||||||
#-----------------------
|
#-----------------------
|
||||||
#
|
#
|
||||||
|
|||||||
@ -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>);
|
||||||
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
}
|
||||||
|
|||||||
@ -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 {}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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()) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface_receiver.listen(move |_| Ok(()))?;
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user