Commit dac7a0b7 authored by Milan Pässler's avatar Milan Pässler 🐈

First demo for ethernet over Qaul

parent e330ec97
......@@ -178,15 +178,6 @@ dependencies = [
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "example-app"
version = "0.1.0"
dependencies = [
"libqaul 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
"netmod-mem 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
"ratman 0.0.0 (git+https://git.open-communication.net/qaul/qaul.net)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
......@@ -317,7 +308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libqaul"
version = "0.1.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
dependencies = [
"alexandria 0.1.0 (git+https://git.open-communication.net/qaul/alexandria)",
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -336,7 +327,7 @@ dependencies = [
[[package]]
name = "libqaul-ipc"
version = "0.1.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
[[package]]
name = "log"
......@@ -416,7 +407,7 @@ dependencies = [
[[package]]
name = "netmod-mem"
version = "0.1.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
dependencies = [
"ratman-identity 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
"ratman-netmod 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
......@@ -480,6 +471,16 @@ dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "qaul-switch"
version = "0.1.0"
dependencies = [
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"libqaul 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
"netmod-mem 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
"ratman 0.0.0 (git+https://git.open-communication.net/qaul/qaul.net)",
]
[[package]]
name = "quote"
version = "1.0.2"
......@@ -528,7 +529,7 @@ dependencies = [
[[package]]
name = "ratman"
version = "0.0.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
dependencies = [
"async-std 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"conjoiner-engine 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -541,7 +542,7 @@ dependencies = [
[[package]]
name = "ratman-identity"
version = "0.1.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
dependencies = [
"blake2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -551,7 +552,7 @@ dependencies = [
[[package]]
name = "ratman-netmod"
version = "0.1.0"
source = "git+https://git.open-communication.net/qaul/qaul.net#90267de86ebd4174a6db35f90c934fb8c265ff1b"
source = "git+https://git.open-communication.net/qaul/qaul.net#046923269e77932c369355955a6bb175db4ecb2a"
dependencies = [
"conjoiner-engine 1.2.4-alpha.0 (git+https://git.open-communication.net/qaul/conjoiner-engine)",
"ratman-identity 0.1.0 (git+https://git.open-communication.net/qaul/qaul.net)",
......
[package]
name = "example-app"
name = "qaul-switch"
version = "0.1.0"
authors = ["YOU <you@example.com>"]
authors = ["Milan Pässler <me@pbb.lc>"]
edition = "2018"
# This app depends on libqaul and the underlying routing layer
[dependencies]
libqaul = { git = "https://git.open-communication.net/qaul/qaul.net" }
ratman = { git = "https://git.open-communication.net/qaul/qaul.net" }
netmod-mem = { git = "https://git.open-communication.net/qaul/qaul.net" }
\ No newline at end of file
netmod-mem = { git = "https://git.open-communication.net/qaul/qaul.net" }
libc = "0.2"
This diff is collapsed.
#![allow(unused)]
use libqaul::Qaul;
mod tap_linux;
use libqaul::{messages::Recipient, users::UserAuth, Qaul};
use ratman::Router;
use netmod_mem::MemMod;
use std::sync::Arc;
use std::convert::TryFrom;
use tap_linux::TapSocket;
use std::time::Duration;
const MAX_UDP_SIZE: usize = (1 << 16) - 1;
const ASC_NAME: &'static str = "qaul-switch";
#[derive(Debug)]
pub enum Error {
Socket(String),
Bind(String),
FCntl(String),
EventQueue(String),
IOCtl(String),
Connect(String),
SetSockOpt(String),
InvalidTunnelName,
Timer(String),
IfaceRead(i32),
DropPrivileges(String),
ApiSocket(std::io::Error),
}
struct TestNetwork {
q1: Arc<Qaul>,
......@@ -45,6 +69,56 @@ fn init_network() -> TestNetwork {
}
}
fn init_node(iface_name: &str, q: Arc<Qaul>, u1: UserAuth, u2: UserAuth) {
let iface = TapSocket::new(iface_name).unwrap().set_non_blocking().unwrap();
let mut src_buf = [0u8; MAX_UDP_SIZE];
let mtu = iface.mtu().unwrap();
{
let iface = iface.clone();
// Then we setup a messaging endponti on note u1
q.services().register(ASC_NAME).unwrap();
q.messages().listen(u1.clone(), ASC_NAME, move |msg| {
iface.write(&msg.payload);
Ok(())
}).unwrap();
}
std::thread::spawn(move || {
loop {
while let Ok(src) = iface.read(&mut src_buf[..mtu]) {
// and send a message to u2
q
.messages()
.send(u1.clone(), Recipient::User(u2.0), ASC_NAME, src.to_vec())
.unwrap();
}
}
});
}
fn main() {
let _network = init_network();
// Generate two user profiles on node 1 and 3
let u1 = _network.q1.users().create("abc").unwrap();
let u2 = _network.q3.users().create("abc").unwrap();
// Manually make Routers discover each other
#[allow(deprecated)]
{
_network.q1.router().discover(u2.0, 0);
_network.q2.router().discover(u1.0, 0);
_network.q2.router().discover(u2.0, 1);
_network.q3.router().discover(u1.0, 0);
}
init_node("foo1", _network.q1, u1.clone(), u2.clone());
init_node("foo2", _network.q3, u2.clone(), u1.clone());
loop {
std::thread::sleep(Duration::from_millis(1000));
}
}
// Copyright (c) 2019 Cloudflare, Inc. All rights reserved.
// SPDX-License-Identifier: BSD-3-Clause
use super::Error;
use libc::*;
use std::os::unix::io::{AsRawFd, RawFd};
pub fn errno() -> i32 {
unsafe { *__errno_location() }
}
pub fn errno_str() -> String {
let strerr = unsafe { strerror(*__errno_location()) };
let c_str = unsafe { std::ffi::CStr::from_ptr(strerr) };
c_str.to_string_lossy().into_owned()
}
const TUNSETIFF: u64 = 0x4004_54ca;
#[repr(C)]
union IfrIfru {
ifru_addr: sockaddr,
ifru_addr_v4: sockaddr_in,
ifru_addr_v6: sockaddr_in,
ifru_dstaddr: sockaddr,
ifru_broadaddr: sockaddr,
ifru_flags: c_short,
ifru_metric: c_int,
ifru_mtu: c_int,
ifru_phys: c_int,
ifru_media: c_int,
ifru_intval: c_int,
//ifru_data: caddr_t,
//ifru_devmtu: ifdevmtu,
//ifru_kpi: ifkpi,
ifru_wake_flags: u32,
ifru_route_refcnt: u32,
ifru_cap: [c_int; 2],
ifru_functional_type: u32,
}
#[repr(C)]
pub struct ifreq {
ifr_name: [c_uchar; IFNAMSIZ],
ifr_ifru: IfrIfru,
}
#[derive(Default, Debug, Clone)]
pub struct TapSocket {
fd: RawFd,
name: String,
}
impl Drop for TapSocket {
fn drop(&mut self) {
unsafe { close(self.fd) };
}
}
impl AsRawFd for TapSocket {
fn as_raw_fd(&self) -> RawFd {
self.fd
}
}
impl TapSocket {
pub fn new(name: &str) -> Result<TapSocket, Error> {
let fd = match unsafe { open(b"/dev/net/tun\0".as_ptr() as _, O_RDWR) } {
-1 => return Err(Error::Socket(errno_str())),
fd => fd,
};
let iface_name = name.as_bytes();
let mut ifr = ifreq {
ifr_name: [0; IFNAMSIZ],
ifr_ifru: IfrIfru {
ifru_flags: (IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE) as _,
},
};
if iface_name.len() >= ifr.ifr_name.len() {
return Err(Error::InvalidTunnelName);
}
ifr.ifr_name[..iface_name.len()].copy_from_slice(iface_name);
if unsafe { ioctl(fd, TUNSETIFF as _, &ifr) } < 0 {
return Err(Error::IOCtl(errno_str()));
}
let name = name.to_string();
Ok(TapSocket { fd, name })
}
pub fn name(&self) -> Result<String, Error> {
Ok(self.name.clone())
}
pub fn set_non_blocking(self) -> Result<TapSocket, Error> {
match unsafe { fcntl(self.fd, F_GETFL) } {
-1 => Err(Error::FCntl(errno_str())),
flags => match unsafe { fcntl(self.fd, F_SETFL, flags | O_NONBLOCK) } {
-1 => Err(Error::FCntl(errno_str())),
_ => Ok(self),
},
}
}
/// Get the current MTU value
pub fn mtu(&self) -> Result<usize, Error> {
let fd = match unsafe { socket(AF_INET, SOCK_STREAM, IPPROTO_IP) } {
-1 => return Err(Error::Socket(errno_str())),
fd => fd,
};
let name = self.name()?;
let iface_name: &[u8] = name.as_ref();
let mut ifr = ifreq {
ifr_name: [0; IF_NAMESIZE],
ifr_ifru: IfrIfru { ifru_mtu: 0 },
};
ifr.ifr_name[..iface_name.len()].copy_from_slice(iface_name);
if unsafe { ioctl(fd, SIOCGIFMTU as _, &ifr) } < 0 {
return Err(Error::IOCtl(errno_str()));
}
unsafe { close(fd) };
Ok(unsafe { ifr.ifr_ifru.ifru_mtu } as _)
}
pub fn write(&self, buf: &[u8]) -> usize {
match unsafe { write(self.fd, buf.as_ptr() as _, buf.len() as _) } {
-1 => 0,
n => n as usize,
}
}
pub fn read<'a>(&self, dst: &'a mut [u8]) -> Result<&'a mut [u8], Error> {
match unsafe { read(self.fd, dst.as_mut_ptr() as _, dst.len()) } {
-1 => Err(Error::IfaceRead(errno())),
n => Ok(&mut dst[..n as usize]),
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment