[quicktap] work on linux tun drivers

This commit is contained in:
core 2022-12-09 23:03:28 -05:00
parent 9a3e367a4c
commit bd9e953352
Signed by: core
GPG Key ID: FDBF740DADDCEECF
15 changed files with 166 additions and 16 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

12
.idea/elaeis4.iml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/quicktap-cli/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/quicktap/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/elaeis4.iml" filepath="$PROJECT_DIR$/.idea/elaeis4.iml" />
</modules>
</component>
</project>

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/wginterface" vcs="Git" />
</component>
</project>

View File

@ -1,4 +1,5 @@
[workspace] [workspace]
members = [ members = [
"wginterface" "quicktap", # Fast WireGuard implementation library
"quicktap-cli", # A userspace Wireguard implementation (wrapper around quicktap)
] ]

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# Elaeis 4.0
Elaeis is a implementation of the WireGuard protocol (quicktap) and a management system built around it (elaeis itself).

View File

@ -1,8 +1,9 @@
[package] [package]
name = "wginterface" name = "quicktap-cli"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
quicktap = { path = "../quicktap", version = "0.1.0" }

3
quicktap-cli/src/main.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

13
quicktap/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "quicktap"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cidr = "0.2.1"
etherparse = "0.13.0"
[target.'cfg(unix)'.dependencies]
tun = "0.5.4"

View File

@ -0,0 +1,79 @@
use std::error::Error;
use std::io;
use std::io::Read;
use etherparse::IpHeader;
use tun::platform::Device;
use crate::drivers::tungeneric::{GenericDriver, GenericInterface, TunPacket};
pub struct TunDevice {
device: Device,
read_buf: [u8; 4096],
read_offset: usize,
packet_buf: [u8; 4096],
}
impl GenericDriver for TunDevice {
/// Create a new TunDevice with the provided generic interface configuration
fn new(config: &GenericInterface) -> Result<Self, Box<dyn Error>> {
let mut device_config = tun::Configuration::default();
device_config.address(config.address.address())?;
device_config.netmask(config.address.mask())?;
device_config.name(&config.name)?;
if let Some(mtu) = config.mtu {
device_config.mtu(mtu)?;
}
//config.platform(|config| {
// config.packet_information(true);
//});
Ok(Self {
device: tun::create(&device_config)?,
read_buf: [0u8; 4096],
read_offset: 0,
packet_buf: [0u8; 4096],
})
}
/// Attempt to read a packet from the interface. If no packet is found, append it to an internal buffer and return WouldBlock.
/// Upon finding a successful packet inside the internal buffer, or the .clear() method being called, the internal buffer will be cleared.
fn read(&mut self) -> Result<TunPacket, Box<dyn Error>> {
self.packet_buf = [0u8; 4096];
let read_amt = self.device.read(&mut self.packet_buf)?;
let ip_header = IpHeader::from_slice(&self.packet_buf);
if let Ok((packet_header, _, _)) = ip_header {
// Found a packet. Clear read buffers
self.read_offset = 0;
self.read_buf = [0u8; 4096];
Ok(TunPacket {
header: packet_header,
packet: *self.packet_buf,
})
}
if &self.read_offset + read_amt > 4096 {
// packet is too big
io::Error::new(io::ErrorKind::InvalidData, "Too much non-packet data recieved on network")?;
}
self.read_buf[&self.read_offset..] = &self.packet_buf;
&self.read_offset += read_amt;
let ip_header = IpHeader::from_slice(&self.read_buf);
if let Ok((packet_header, _, _)) = ip_header {
// Found a packet. Clear read buffers
self.read_offset = 0;
self.read_buf = [0u8; 4096];
Ok(TunPacket {
header: packet_header,
packet: *self.packet_buf,
})
}
io::Error::new(io::ErrorKind::WouldBlock, "No packets detected yet")?
}
fn clear(&mut self) {
self.read_buf = [0u8; 4096];
self.read_offset = 0;
}
fn write(&mut self, packet: Box<TunPacket>) -> Result<(), Box<dyn Error>> {
todo!()
}
}

View File

@ -0,0 +1,5 @@
#[cfg(unix)]
#[path = "linux.rs"]
pub mod tun; // Tun/tap drivers for Linux
pub mod tungeneric;

View File

@ -0,0 +1,22 @@
use std::error::Error;
use cidr::IpInet;
use etherparse::{IpHeader, SlicedPacket};
pub struct TunPacket {
pub header: IpHeader,
pub packet: [u8]
}
pub trait GenericDriver {
fn new(config: &GenericInterface) -> Result<Self, Box<dyn Error>>;
fn read(&mut self) -> Result<TunPacket, Box<dyn Error>>;
fn clear(&mut self);
fn write(&mut self, packet: TunPacket) -> Result<(), Box<dyn Error>>;
}
pub struct GenericInterface {
pub address: IpInet,
pub mtu: Option<i32>,
pub name: String
}

1
quicktap/src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod drivers; // Baremetal network drivers for various platforms

View File

@ -1,14 +0,0 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}