* Port previous ethernet scheme

* Add ipd

* Fix initfs rebuilds, use QEMU user networking addresses in ipd

* Add tcp/udp, netutils, dns, and network config

* Add fsync to network driver

* Add dns, router, subnet by default

* Fix e1000 driver. Make ethernet and IP non-blocking to avoid deadlocks

* Add orbital server, WIP

* Add futex

* Add orbutils and orbital

* Update libstd, orbutils, and orbital
Move ANSI key encoding to vesad

* Add orbital assets

* Update orbital

* Update to add login manager

* Add blocking primitives, block for most things except waitpid, update orbital

* Wait in waitpid and IRQ, improvements for other waits

* Fevent in root scheme

* WIP: Switch to using fevent

* Reorganize

* Event based e1000d driver

* Superuser-only access to some network schemes, display, and disk

* Superuser root and irq schemes

* Fix orbital
This commit is contained in:
Jeremy Soller 2016-10-13 17:21:42 -06:00 committed by GitHub
parent 372d44f88c
commit 224c43f761
92 changed files with 3415 additions and 473 deletions

7
schemes/tcpd/Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "tcpd"
version = "0.1.0"
[dependencies]
resource_scheme = { path = "../../crates/resource_scheme/" }
syscall = { path = "../../syscall/" }

217
schemes/tcpd/src/common.rs Normal file
View file

@ -0,0 +1,217 @@
use std::{mem, slice, u8, u16, u32};
pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] };
#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
#[repr(packed)]
pub struct n16(u16);
impl n16 {
pub fn new(value: u16) -> Self {
n16(value.to_be())
}
pub fn get(&self) -> u16 {
u16::from_be(self.0)
}
pub fn set(&mut self, value: u16) {
self.0 = value.to_be();
}
}
#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
#[repr(packed)]
pub struct n32(u32);
impl n32 {
pub fn new(value: u32) -> Self {
n32(value.to_be())
}
pub fn get(&self) -> u32 {
u32::from_be(self.0)
}
pub fn set(&mut self, value: u32) {
self.0 = value.to_be();
}
}
#[derive(Copy, Clone)]
pub struct Ipv4Addr {
pub bytes: [u8; 4],
}
impl Ipv4Addr {
pub fn equals(&self, other: Self) -> bool {
for i in 0..4 {
if self.bytes[i] != other.bytes[i] {
return false;
}
}
true
}
pub fn from_str(string: &str) -> Self {
let mut addr = Ipv4Addr { bytes: [0, 0, 0, 0] };
let mut i = 0;
for part in string.split('.') {
let octet = part.parse::<u8>().unwrap_or(0);
match i {
0 => addr.bytes[0] = octet,
1 => addr.bytes[1] = octet,
2 => addr.bytes[2] = octet,
3 => addr.bytes[3] = octet,
_ => break,
}
i += 1;
}
addr
}
pub fn to_string(&self) -> String {
let mut string = String::new();
for i in 0..4 {
if i > 0 {
string = string + ".";
}
string = string + &format!("{}", self.bytes[i]);
}
string
}
}
#[derive(Copy, Clone)]
pub struct Checksum {
pub data: u16,
}
impl Checksum {
pub unsafe fn check(&self, mut ptr: usize, mut len: usize) -> bool {
let mut sum: usize = 0;
while len > 1 {
sum += *(ptr as *const u16) as usize;
len -= 2;
ptr += 2;
}
if len > 0 {
sum += *(ptr as *const u8) as usize;
}
while (sum >> 16) > 0 {
sum = (sum & 0xFFFF) + (sum >> 16);
}
sum == 0xFFFF
}
pub unsafe fn calculate(&mut self, ptr: usize, len: usize) {
self.data = 0;
let sum = Checksum::sum(ptr, len);
self.data = Checksum::compile(sum);
}
pub unsafe fn sum(mut ptr: usize, mut len: usize) -> usize {
let mut sum = 0;
while len > 1 {
sum += *(ptr as *const u16) as usize;
len -= 2;
ptr += 2;
}
if len > 0 {
sum += *(ptr as *const u8) as usize;
}
sum
}
pub fn compile(mut sum: usize) -> u16 {
while (sum >> 16) > 0 {
sum = (sum & 0xFFFF) + (sum >> 16);
}
0xFFFF - (sum as u16)
}
}
pub const TCP_FIN: u16 = 1;
pub const TCP_SYN: u16 = 1 << 1;
pub const TCP_RST: u16 = 1 << 2;
pub const TCP_PSH: u16 = 1 << 3;
pub const TCP_ACK: u16 = 1 << 4;
#[derive(Copy, Clone)]
#[repr(packed)]
pub struct TcpHeader {
pub src: n16,
pub dst: n16,
pub sequence: n32,
pub ack_num: n32,
pub flags: n16,
pub window_size: n16,
pub checksum: Checksum,
pub urgent_pointer: n16,
}
pub struct Tcp {
pub header: TcpHeader,
pub options: Vec<u8>,
pub data: Vec<u8>,
}
impl Tcp {
pub fn checksum(&mut self, src_addr: &Ipv4Addr, dst_addr: &Ipv4Addr) {
self.header.checksum.data = 0;
let proto = n16::new(0x06);
let segment_len = n16::new((mem::size_of::<TcpHeader>() + self.options.len() + self.data.len()) as u16);
self.header.checksum.data = Checksum::compile(unsafe {
Checksum::sum(src_addr.bytes.as_ptr() as usize, src_addr.bytes.len()) +
Checksum::sum(dst_addr.bytes.as_ptr() as usize, dst_addr.bytes.len()) +
Checksum::sum((&proto as *const n16) as usize, mem::size_of::<n16>()) +
Checksum::sum((&segment_len as *const n16) as usize, mem::size_of::<n16>()) +
Checksum::sum((&self.header as *const TcpHeader) as usize, mem::size_of::<TcpHeader>()) +
Checksum::sum(self.options.as_ptr() as usize, self.options.len()) +
Checksum::sum(self.data.as_ptr() as usize, self.data.len())
});
}
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() >= mem::size_of::<TcpHeader>() {
unsafe {
let header = *(bytes.as_ptr() as *const TcpHeader);
let header_len = ((header.flags.get() & 0xF000) >> 10) as usize;
return Some(Tcp {
header: header,
options: bytes[mem::size_of::<TcpHeader>()..header_len].to_vec(),
data: bytes[header_len..bytes.len()].to_vec(),
});
}
}
None
}
pub fn to_bytes(&self) -> Vec<u8> {
unsafe {
let header_ptr: *const TcpHeader = &self.header;
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
mem::size_of::<TcpHeader>()));
ret.extend_from_slice(&self.options);
ret.extend_from_slice(&self.data);
ret
}
}
}

30
schemes/tcpd/src/main.rs Normal file
View file

@ -0,0 +1,30 @@
#![feature(rand)]
extern crate resource_scheme;
extern crate syscall;
use std::fs::File;
use std::io::{Read, Write};
use std::thread;
use resource_scheme::ResourceScheme;
use syscall::Packet;
use scheme::TcpScheme;
pub mod common;
pub mod resource;
pub mod scheme;
fn main() {
thread::spawn(move || {
let mut socket = File::create(":tcp").expect("tcpd: failed to create tcp scheme");
let scheme = TcpScheme;
loop {
let mut packet = Packet::default();
socket.read(&mut packet).expect("tcpd: failed to read events from tcp scheme");
scheme.handle(&mut packet);
socket.write(&packet).expect("tcpd: failed to write responses to tcp scheme");
}
});
}

View file

@ -0,0 +1,328 @@
use std::{cmp, mem};
use std::cell::UnsafeCell;
use std::sync::Arc;
use resource_scheme::Resource;
use syscall;
use syscall::error::*;
use common::{n16, n32, Ipv4Addr, Checksum, IP_ADDR, Tcp, TcpHeader, TCP_SYN, TCP_PSH, TCP_FIN, TCP_ACK};
pub struct TcpStream {
pub ip: usize,
pub peer_addr: Ipv4Addr,
pub peer_port: u16,
pub host_port: u16,
pub sequence: u32,
pub acknowledge: u32,
pub finished: bool
}
impl TcpStream {
fn path(&self, buf: &mut [u8]) -> Result<usize> {
let path_string = format!("tcp:{}:{}/{}", self.peer_addr.to_string(), self.peer_port, self.host_port);
let path = path_string.as_bytes();
for (b, p) in buf.iter_mut().zip(path.iter()) {
*b = *p;
}
Ok(cmp::min(buf.len(), path.len()))
}
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
if self.finished {
return Ok(0);
}
loop {
let mut bytes = [0; 65536];
let count = try!(syscall::read(self.ip, &mut bytes));
if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
if segment.header.dst.get() == self.host_port && segment.header.src.get() == self.peer_port {
//println!("Read: {}=={} {:X}: {}", segment.header.sequence.get(), self.acknowledge, segment.header.flags.get(), segment.data.len());
if self.acknowledge == segment.header.sequence.get() {
if segment.header.flags.get() & TCP_FIN == TCP_FIN {
self.finished = true;
}
if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK {
let flags = if self.finished {
TCP_ACK | TCP_FIN
} else {
TCP_ACK
};
// Send ACK
self.acknowledge += segment.data.len() as u32;
let mut tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | flags),
window_size: n16::new(65535),
checksum: Checksum {
data: 0
},
urgent_pointer: n16::new(0)
},
options: Vec::new(),
data: Vec::new()
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
//println!("Sending read ack: {} {} {:X}", tcp.header.sequence.get(), tcp.header.ack_num.get(), tcp.header.flags.get());
let _ = syscall::write(self.ip, &tcp.to_bytes());
// TODO: Support broken packets (one packet in two buffers)
let mut i = 0;
while i < buf.len() && i < segment.data.len() {
buf[i] = segment.data[i];
i += 1;
}
return Ok(i);
}
} else {
println!("TCP: MISMATCH: {}=={}", segment.header.sequence.get(), self.acknowledge);
}
} else {
println!("TCP: WRONG PORT {}=={} && {}=={}", segment.header.dst.get(), self.host_port, segment.header.src.get(), self.peer_port);
}
}
}
}
fn write(&mut self, buf: &[u8]) -> Result<usize> {
let tcp_data = Vec::from(buf);
let mut tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new((((mem::size_of::<TcpHeader>()) << 10) & 0xF000) as u16 | TCP_PSH |
TCP_ACK),
window_size: n16::new(65535),
checksum: Checksum { data: 0 },
urgent_pointer: n16::new(0),
},
options: Vec::new(),
data: tcp_data,
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(size) => {
loop {
// Wait for ACK
let mut bytes = [0; 65536];
match syscall::read(self.ip, &mut bytes) {
Ok(count) => {
if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
if segment.header.dst.get() == self.host_port &&
segment.header.src.get() == self.peer_port {
return if (segment.header.flags.get() & (TCP_SYN | TCP_ACK)) == TCP_ACK {
self.sequence = segment.header.ack_num.get();
self.acknowledge = segment.header.sequence.get();
Ok(size)
} else {
Err(Error::new(EPIPE))
};
}
}
}
Err(err) => return Err(err),
}
}
}
Err(err) => Err(err),
}
}
fn sync(&mut self) -> Result<usize> {
syscall::fsync(self.ip)
}
/// Etablish client
pub fn client_establish(&mut self) -> bool {
// Send SYN
let mut tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_SYN),
window_size: n16::new(65535),
checksum: Checksum { data: 0 },
urgent_pointer: n16::new(0),
},
options: Vec::new(),
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(_) => {
loop {
// Wait for SYN-ACK
let mut bytes = [0; 65536];
match syscall::read(self.ip, &mut bytes) {
Ok(count) => {
if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
if segment.header.dst.get() == self.host_port &&
segment.header.src.get() == self.peer_port {
return if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK {
self.sequence = segment.header.ack_num.get();
self.acknowledge = segment.header.sequence.get();
self.acknowledge += 1;
tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_ACK),
window_size: n16::new(65535),
checksum: Checksum {
data: 0
},
urgent_pointer: n16::new(0)
},
options: Vec::new(),
data: Vec::new()
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
let _ = syscall::write(self.ip, &tcp.to_bytes());
true
} else {
false
};
}
}
}
Err(_) => return false,
}
}
}
Err(_) => false,
}
}
/// Try to establish a server connection
pub fn server_establish(&mut self, _: Tcp) -> bool {
// Send SYN-ACK
self.acknowledge += 1;
let mut tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_SYN |
TCP_ACK),
window_size: n16::new(65535),
checksum: Checksum { data: 0 },
urgent_pointer: n16::new(0),
},
options: Vec::new(),
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(_) => {
loop {
// Wait for ACK
let mut bytes = [0; 65536];
match syscall::read(self.ip, &mut bytes) {
Ok(count ) => {
if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
if segment.header.dst.get() == self.host_port &&
segment.header.src.get() == self.peer_port {
return if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK {
self.sequence = segment.header.ack_num.get();
self.acknowledge = segment.header.sequence.get();
true
} else {
false
};
}
}
}
Err(_) => return false,
}
}
}
Err(_) => false,
}
}
}
impl Drop for TcpStream {
fn drop(&mut self) {
// Send FIN-ACK
let mut tcp = Tcp {
header: TcpHeader {
src: n16::new(self.host_port),
dst: n16::new(self.peer_port),
sequence: n32::new(self.sequence),
ack_num: n32::new(self.acknowledge),
flags: n16::new((((mem::size_of::<TcpHeader>()) << 10) & 0xF000) as u16 | TCP_FIN | TCP_ACK),
window_size: n16::new(65535),
checksum: Checksum { data: 0 },
urgent_pointer: n16::new(0),
},
options: Vec::new(),
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
let _ = syscall::write(self.ip, &tcp.to_bytes());
let _ = syscall::close(self.ip);
}
}
/// A TCP resource
pub struct TcpResource {
pub stream: Arc<UnsafeCell<TcpStream>>
}
impl Resource for TcpResource {
fn dup(&self) -> Result<Box<TcpResource>> {
Ok(Box::new(TcpResource {
stream: self.stream.clone()
}))
}
fn path(&self, buf: &mut [u8]) -> Result<usize> {
unsafe { (*self.stream.get()).path(buf) }
}
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
unsafe { (*self.stream.get()).read(buf) }
}
fn write(&mut self, buf: &[u8]) -> Result<usize> {
unsafe { (*self.stream.get()).write(buf) }
}
fn sync(&mut self) -> Result<usize> {
unsafe { (*self.stream.get()).sync() }
}
}

View file

@ -0,0 +1,94 @@
use std::cell::UnsafeCell;
use std::rand;
use std::sync::Arc;
use std::{str, u16};
use resource_scheme::ResourceScheme;
use syscall;
use syscall::error::{Error, Result, ENOENT, EINVAL};
use syscall::flag::O_RDWR;
use common::{Ipv4Addr, Tcp, TCP_SYN, TCP_ACK};
use resource::{TcpResource, TcpStream};
/// A TCP scheme
pub struct TcpScheme;
impl ResourceScheme<TcpResource> for TcpScheme {
fn open_resource(&self, url: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<Box<TcpResource>> {
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
let mut parts = path.split('/');
let remote = parts.next().unwrap_or("");
let path = parts.next().unwrap_or("");
let mut remote_parts = remote.split(':');
let host = remote_parts.next().unwrap_or("");
let port = remote_parts.next().unwrap_or("");
if ! host.is_empty() && ! port.is_empty() {
let peer_addr = Ipv4Addr::from_str(host);
let peer_port = port.parse::<u16>().unwrap_or(0);
let host_port = (rand() % 32768 + 32768) as u16;
match syscall::open(&format!("ip:{}/6", peer_addr.to_string()), O_RDWR) {
Ok(ip) => {
let mut stream = TcpStream {
ip: ip,
peer_addr: peer_addr,
peer_port: peer_port,
host_port: host_port,
sequence: rand() as u32,
acknowledge: 0,
finished: false
};
if stream.client_establish() {
return Ok(Box::new(TcpResource {
stream: Arc::new(UnsafeCell::new(stream))
}));
}
}
Err(err) => return Err(err),
}
} else if ! path.is_empty() {
let host_port = path.parse::<u16>().unwrap_or(0);
while let Ok(ip) = syscall::open("ip:/6", O_RDWR) {
let mut bytes = [0; 65536];
match syscall::read(ip, &mut bytes) {
Ok(count) => {
if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
if segment.header.dst.get() == host_port && segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN {
let mut path = [0; 256];
if let Ok(path_count) = syscall::fpath(ip, &mut path) {
let ip_reference = unsafe { str::from_utf8_unchecked(&path[.. path_count]) }.split(':').nth(1).unwrap_or("");
let ip_remote = ip_reference.split('/').next().unwrap_or("");
let peer_addr = ip_remote.split(':').next().unwrap_or("");
let mut stream = TcpStream {
ip: ip,
peer_addr: Ipv4Addr::from_str(peer_addr),
peer_port: segment.header.src.get(),
host_port: host_port,
sequence: rand() as u32,
acknowledge: segment.header.sequence.get(),
finished: false
};
if stream.server_establish(segment) {
return Ok(Box::new(TcpResource {
stream: Arc::new(UnsafeCell::new(stream))
}));
}
}
}
}
}
Err(err) => return Err(err),
}
}
}
Err(Error::new(ENOENT))
}
}