2016-10-23 23:26:36 +02:00
|
|
|
use std::collections::{BTreeMap, VecDeque};
|
|
|
|
use std::fs::File;
|
2016-10-26 21:19:56 +02:00
|
|
|
use std::io::{self, Read, Write};
|
2016-10-23 23:26:36 +02:00
|
|
|
use std::os::unix::io::AsRawFd;
|
|
|
|
use std::{cmp, str, u16};
|
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
2016-10-14 01:21:42 +02:00
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
use netutils::{getcfg, MacAddr, EthernetII};
|
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
2016-10-14 01:21:42 +02:00
|
|
|
use syscall;
|
2016-10-31 17:49:00 +01:00
|
|
|
use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EIO, EWOULDBLOCK};
|
2016-10-26 21:19:56 +02:00
|
|
|
use syscall::flag::O_NONBLOCK;
|
2016-10-23 23:26:36 +02:00
|
|
|
use syscall::scheme::SchemeMut;
|
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
2016-10-14 01:21:42 +02:00
|
|
|
|
2016-10-23 23:26:36 +02:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Handle {
|
2016-10-26 21:19:56 +02:00
|
|
|
/// The flags this handle was opened with
|
|
|
|
flags: usize,
|
2016-10-23 23:26:36 +02:00
|
|
|
/// The Host's MAC address
|
|
|
|
pub host_addr: MacAddr,
|
|
|
|
/// The ethernet type
|
|
|
|
pub ethertype: u16,
|
|
|
|
/// The data
|
|
|
|
pub frames: VecDeque<EthernetII>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EthernetScheme {
|
|
|
|
network: File,
|
|
|
|
next_id: usize,
|
|
|
|
pub handles: BTreeMap<usize, Handle>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EthernetScheme {
|
|
|
|
pub fn new(network: File) -> EthernetScheme {
|
|
|
|
EthernetScheme {
|
|
|
|
network: network,
|
|
|
|
next_id: 1,
|
|
|
|
handles: BTreeMap::new(),
|
|
|
|
}
|
|
|
|
}
|
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
2016-10-14 01:21:42 +02:00
|
|
|
|
2016-10-23 23:26:36 +02:00
|
|
|
//TODO: Minimize allocation
|
|
|
|
//TODO: Reduce iteration cost (use BTreeMap of ethertype to handle?)
|
|
|
|
pub fn input(&mut self) -> io::Result<usize> {
|
2016-10-26 21:19:56 +02:00
|
|
|
let mut total = 0;
|
|
|
|
loop {
|
|
|
|
let mut bytes = [0; 65536];
|
|
|
|
let count = self.network.read(&mut bytes)?;
|
|
|
|
if count == 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) {
|
|
|
|
for (_id, handle) in self.handles.iter_mut() {
|
|
|
|
if frame.header.ethertype.get() == handle.ethertype {
|
|
|
|
handle.frames.push_back(frame.clone());
|
2016-10-23 23:57:04 +02:00
|
|
|
}
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
2016-10-26 21:19:56 +02:00
|
|
|
total += count;
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
|
|
|
}
|
2016-10-26 21:19:56 +02:00
|
|
|
Ok(total)
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
|
|
|
}
|
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
2016-10-14 01:21:42 +02:00
|
|
|
|
2016-10-23 23:26:36 +02:00
|
|
|
impl SchemeMut for EthernetScheme {
|
2016-10-26 21:19:56 +02:00
|
|
|
fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
|
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
2016-10-14 01:21:42 +02:00
|
|
|
if uid == 0 {
|
2016-10-31 17:49:00 +01:00
|
|
|
let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?);
|
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
2016-10-14 01:21:42 +02:00
|
|
|
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
let ethertype = u16::from_str_radix(path, 16).unwrap_or(0);
|
|
|
|
|
|
|
|
let next_id = self.next_id;
|
|
|
|
self.next_id += 1;
|
|
|
|
|
|
|
|
self.handles.insert(next_id, Handle {
|
|
|
|
flags: flags,
|
|
|
|
host_addr: mac_addr,
|
|
|
|
ethertype: ethertype,
|
|
|
|
frames: VecDeque::new()
|
|
|
|
});
|
|
|
|
|
|
|
|
Ok(next_id)
|
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
2016-10-14 01:21:42 +02:00
|
|
|
} else {
|
|
|
|
Err(Error::new(EACCES))
|
|
|
|
}
|
|
|
|
}
|
2016-10-23 23:26:36 +02:00
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
|
2016-10-23 23:26:36 +02:00
|
|
|
let next_id = self.next_id;
|
|
|
|
self.next_id += 1;
|
|
|
|
|
|
|
|
let handle = {
|
|
|
|
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
handle.clone()
|
|
|
|
};
|
|
|
|
|
|
|
|
self.handles.insert(next_id, handle);
|
|
|
|
|
|
|
|
Ok(next_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
|
|
|
let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
|
|
|
|
if let Some(frame) = handle.frames.pop_front() {
|
2016-10-26 21:19:56 +02:00
|
|
|
let data = frame.to_bytes();
|
|
|
|
for (b, d) in buf.iter_mut().zip(data.iter()) {
|
2016-10-23 23:26:36 +02:00
|
|
|
*b = *d;
|
|
|
|
}
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
Ok(cmp::min(buf.len(), data.len()))
|
|
|
|
} else if handle.flags & O_NONBLOCK == O_NONBLOCK {
|
|
|
|
Ok(0)
|
2016-10-23 23:26:36 +02:00
|
|
|
} else {
|
|
|
|
Err(Error::new(EWOULDBLOCK))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
|
|
|
|
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
if let Some(mut frame) = EthernetII::from_bytes(buf) {
|
|
|
|
frame.header.src = handle.host_addr;
|
|
|
|
frame.header.ethertype.set(handle.ethertype);
|
2016-10-31 17:49:00 +01:00
|
|
|
self.network.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))
|
2016-10-26 21:19:56 +02:00
|
|
|
} else {
|
|
|
|
Err(Error::new(EINVAL))
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fevent(&mut self, id: usize, _flags: usize) -> Result<usize> {
|
|
|
|
let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
|
|
|
|
Ok(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
|
|
|
|
let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
let path_string = format!("ethernet:{:X}", handle.ethertype);
|
2016-10-23 23:26:36 +02:00
|
|
|
let path = path_string.as_bytes();
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
let mut i = 0;
|
|
|
|
while i < buf.len() && i < path.len() {
|
|
|
|
buf[i] = path[i];
|
|
|
|
i += 1;
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
|
|
|
|
2016-10-26 21:19:56 +02:00
|
|
|
Ok(i)
|
2016-10-23 23:26:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fsync(&mut self, id: usize) -> Result<usize> {
|
|
|
|
let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
|
|
|
|
|
|
|
|
syscall::fsync(self.network.as_raw_fd())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn close(&mut self, id: usize) -> Result<usize> {
|
|
|
|
let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?;
|
2016-10-26 21:19:56 +02:00
|
|
|
|
2016-10-23 23:26:36 +02:00
|
|
|
drop(handle);
|
2016-10-26 21:19:56 +02:00
|
|
|
|
2016-10-23 23:26:36 +02:00
|
|
|
Ok(0)
|
|
|
|
}
|
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
2016-10-14 01:21:42 +02:00
|
|
|
}
|