Orbital (#16)
* 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:
parent
372d44f88c
commit
224c43f761
92 changed files with 3415 additions and 473 deletions
105
schemes/ethernetd/src/common.rs
Normal file
105
schemes/ethernetd/src/common.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
use std::{mem, slice, u8, u16};
|
||||
|
||||
#[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)]
|
||||
pub struct MacAddr {
|
||||
pub bytes: [u8; 6],
|
||||
}
|
||||
|
||||
impl MacAddr {
|
||||
pub fn equals(&self, other: Self) -> bool {
|
||||
for i in 0..6 {
|
||||
if self.bytes[i] != other.bytes[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Self {
|
||||
let mut addr = MacAddr { bytes: [0, 0, 0, 0, 0, 0] };
|
||||
|
||||
let mut i = 0;
|
||||
for part in string.split('.') {
|
||||
let octet = u8::from_str_radix(part, 16).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,
|
||||
4 => addr.bytes[4] = octet,
|
||||
5 => addr.bytes[5] = octet,
|
||||
_ => break,
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
let mut string = String::new();
|
||||
for i in 0..6 {
|
||||
if i > 0 {
|
||||
string.push('.');
|
||||
}
|
||||
string.push_str(&format!("{:X}", self.bytes[i]));
|
||||
}
|
||||
string
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(packed)]
|
||||
pub struct EthernetIIHeader {
|
||||
pub dst: MacAddr,
|
||||
pub src: MacAddr,
|
||||
pub ethertype: n16,
|
||||
}
|
||||
|
||||
pub struct EthernetII {
|
||||
pub header: EthernetIIHeader,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl EthernetII {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||
if bytes.len() >= mem::size_of::<EthernetIIHeader>() {
|
||||
unsafe {
|
||||
return Some(EthernetII {
|
||||
header: *(bytes.as_ptr() as *const EthernetIIHeader),
|
||||
data: bytes[mem::size_of::<EthernetIIHeader>() ..].to_vec(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let header_ptr: *const EthernetIIHeader = &self.header;
|
||||
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
|
||||
mem::size_of::<EthernetIIHeader>()));
|
||||
ret.extend_from_slice(&self.data);
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
28
schemes/ethernetd/src/main.rs
Normal file
28
schemes/ethernetd/src/main.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
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::EthernetScheme;
|
||||
|
||||
pub mod common;
|
||||
pub mod resource;
|
||||
pub mod scheme;
|
||||
|
||||
fn main() {
|
||||
thread::spawn(move || {
|
||||
let mut socket = File::create(":ethernet").expect("ethernetd: failed to create ethernet scheme");
|
||||
let scheme = EthernetScheme;
|
||||
loop {
|
||||
let mut packet = Packet::default();
|
||||
socket.read(&mut packet).expect("ethernetd: failed to read events from ethernet scheme");
|
||||
scheme.handle(&mut packet);
|
||||
socket.write(&packet).expect("ethernetd: failed to write responses to ethernet scheme");
|
||||
}
|
||||
});
|
||||
}
|
97
schemes/ethernetd/src/resource.rs
Normal file
97
schemes/ethernetd/src/resource.rs
Normal file
|
@ -0,0 +1,97 @@
|
|||
use std::{cmp, mem};
|
||||
|
||||
use resource_scheme::Resource;
|
||||
use syscall;
|
||||
use syscall::error::*;
|
||||
|
||||
use common::{n16, MacAddr, EthernetIIHeader, EthernetII};
|
||||
|
||||
/// A ethernet resource
|
||||
pub struct EthernetResource {
|
||||
/// The network
|
||||
pub network: usize,
|
||||
/// The data
|
||||
pub data: Vec<u8>,
|
||||
/// The MAC addresss
|
||||
pub peer_addr: MacAddr,
|
||||
/// The ethernet type
|
||||
pub ethertype: u16,
|
||||
}
|
||||
|
||||
impl Resource for EthernetResource {
|
||||
fn dup(&self) -> Result<Box<Self>> {
|
||||
let network = try!(syscall::dup(self.network));
|
||||
Ok(Box::new(EthernetResource {
|
||||
network: network,
|
||||
data: self.data.clone(),
|
||||
peer_addr: self.peer_addr,
|
||||
ethertype: self.ethertype,
|
||||
}))
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
let path_string = format!("ethernet:{}/{:X}", self.peer_addr.to_string(), self.ethertype);
|
||||
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.data.is_empty() {
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
mem::swap(&mut self.data, &mut data);
|
||||
|
||||
for (b, d) in buf.iter_mut().zip(data.iter()) {
|
||||
*b = *d;
|
||||
}
|
||||
|
||||
return Ok(cmp::min(buf.len(), data.len()));
|
||||
}
|
||||
|
||||
let mut bytes = [0; 65536];
|
||||
let count = try!(syscall::read(self.network, &mut bytes));
|
||||
|
||||
if let Some(frame) = EthernetII::from_bytes(&bytes[..count]) {
|
||||
if frame.header.ethertype.get() == self.ethertype {
|
||||
for (b, d) in buf.iter_mut().zip(frame.data.iter()) {
|
||||
*b = *d;
|
||||
}
|
||||
|
||||
return Ok(cmp::min(buf.len(), frame.data.len()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize> {
|
||||
let data = Vec::from(buf);
|
||||
|
||||
match syscall::write(self.network, &EthernetII {
|
||||
header: EthernetIIHeader {
|
||||
src: MacAddr { bytes: [0x50, 0x51, 0x52, 0x53, 0x54, 0x55] },
|
||||
dst: self.peer_addr,
|
||||
ethertype: n16::new(self.ethertype),
|
||||
},
|
||||
data: data,
|
||||
}
|
||||
.to_bytes()) {
|
||||
Ok(_) => Ok(buf.len()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn sync(&mut self) -> Result<usize> {
|
||||
syscall::fsync(self.network)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for EthernetResource {
|
||||
fn drop(&mut self) {
|
||||
let _ = syscall::close(self.network);
|
||||
}
|
||||
}
|
65
schemes/ethernetd/src/scheme.rs
Normal file
65
schemes/ethernetd/src/scheme.rs
Normal file
|
@ -0,0 +1,65 @@
|
|||
use std::{str, u16};
|
||||
|
||||
use resource_scheme::ResourceScheme;
|
||||
use syscall;
|
||||
use syscall::error::{Error, Result, EACCES, ENOENT, EINVAL};
|
||||
use syscall::flag::O_RDWR;
|
||||
|
||||
use common::{MacAddr, EthernetII};
|
||||
use resource::EthernetResource;
|
||||
|
||||
pub struct EthernetScheme;
|
||||
|
||||
impl ResourceScheme<EthernetResource> for EthernetScheme {
|
||||
fn open_resource(&self, url: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<Box<EthernetResource>> {
|
||||
if uid == 0 {
|
||||
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
|
||||
let mut parts = path.split("/");
|
||||
if let Some(host_string) = parts.next() {
|
||||
if let Some(ethertype_string) = parts.next() {
|
||||
if let Ok(network) = syscall::open("network:", O_RDWR) {
|
||||
let ethertype = u16::from_str_radix(ethertype_string, 16).unwrap_or(0) as u16;
|
||||
|
||||
if !host_string.is_empty() {
|
||||
return Ok(Box::new(EthernetResource {
|
||||
network: network,
|
||||
data: Vec::new(),
|
||||
peer_addr: MacAddr::from_str(host_string),
|
||||
ethertype: ethertype,
|
||||
}));
|
||||
} else {
|
||||
loop {
|
||||
let mut bytes = [0; 65536];
|
||||
match syscall::read(network, &mut bytes) {
|
||||
Ok(count) => {
|
||||
if let Some(frame) = EthernetII::from_bytes(&bytes[..count]) {
|
||||
if frame.header.ethertype.get() == ethertype {
|
||||
return Ok(Box::new(EthernetResource {
|
||||
network: network,
|
||||
data: frame.data,
|
||||
peer_addr: frame.header.src,
|
||||
ethertype: ethertype,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
println!("Ethernet: Failed to open network:");
|
||||
}
|
||||
} else {
|
||||
println!("Ethernet: No ethertype provided");
|
||||
}
|
||||
} else {
|
||||
println!("Ethernet: No host provided");
|
||||
}
|
||||
|
||||
Err(Error::new(ENOENT))
|
||||
} else {
|
||||
Err(Error::new(EACCES))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue