From 29e3c38c1dc8e5d9e3a403a58c690ffbc88df329 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 29 Oct 2017 20:39:53 -0600 Subject: [PATCH] Remove old schemes, use patched smoltcp, remove log feature --- Cargo.lock | 51 +- Cargo.toml | 20 +- src/ethernetd/main.rs | 112 ---- src/ethernetd/scheme.rs | 169 ------ src/ipd/interface/ethernet.rs | 155 ------ src/ipd/interface/loopback.rs | 50 -- src/ipd/interface/mod.rs | 19 - src/ipd/main.rs | 348 ------------ src/tcpd/main.rs | 982 ---------------------------------- src/udpd/main.rs | 588 -------------------- 10 files changed, 27 insertions(+), 2467 deletions(-) delete mode 100644 src/ethernetd/main.rs delete mode 100644 src/ethernetd/scheme.rs delete mode 100644 src/ipd/interface/ethernet.rs delete mode 100644 src/ipd/interface/loopback.rs delete mode 100644 src/ipd/interface/mod.rs delete mode 100644 src/ipd/main.rs delete mode 100644 src/tcpd/main.rs delete mode 100644 src/udpd/main.rs diff --git a/Cargo.lock b/Cargo.lock index 019cc2f008..cbb61bcc90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,15 +1,3 @@ -[root] -name = "redox_netstack" -version = "0.1.0" -dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", - "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp.git)", -] - [[package]] name = "arg_parser" version = "0.1.0" @@ -148,7 +136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -177,13 +165,13 @@ dependencies = [ [[package]] name = "netutils" version = "0.1.0" -source = "git+https://github.com/redox-os/netutils.git#2c082a38814922125ca402103a1a50d5531f6330" +source = "git+https://github.com/redox-os/netutils.git#a719fa50b065840ffacc81d989e47f258b3e5170" dependencies = [ "arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)", "extra 0.1.0 (git+https://github.com/redox-os/libextra.git)", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "ntpclient 0.0.1 (git+https://github.com/willem66745/ntpclient-rust)", "pbr 1.0.0 (git+https://github.com/a8m/pb)", "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", @@ -205,7 +193,7 @@ name = "num_cpus" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -214,7 +202,7 @@ version = "1.0.0" source = "git+https://github.com/a8m/pb#e9369ed2b94df4f554fe79c2643de41f7338475f" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -231,7 +219,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -250,7 +238,7 @@ dependencies = [ "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -263,6 +251,18 @@ dependencies = [ "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_netstack" +version = "0.1.0" +dependencies = [ + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "netutils 0.1.0 (git+https://github.com/redox-os/netutils.git)", + "rand 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_event 0.1.0 (git+https://github.com/redox-os/event.git)", + "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "smoltcp 0.4.0 (git+https://github.com/redox-os/smoltcp.git)", +] + [[package]] name = "redox_syscall" version = "0.1.31" @@ -283,7 +283,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -314,10 +314,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smoltcp" version = "0.4.0" -source = "git+https://github.com/m-labs/smoltcp.git#f64a99a4e6d744c3a6f3d9a54a0fb3f94e4b0ec8" +source = "git+https://github.com/redox-os/smoltcp.git#a6fc036ad65e07523e271304bb96d99a9f9a2707" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -326,7 +325,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -337,7 +336,7 @@ version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -442,7 +441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5" -"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148" +"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum managed 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d48e8c30a4363e2981fe4db20527f6ab0f32a243bbc75379dea5a64f60dae4" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" @@ -462,7 +461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustls 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17727f4b991294da2c84d75a43c003151ff58072212768800f66c56ee46dca43" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum smoltcp 0.4.0 (git+https://github.com/m-labs/smoltcp.git)" = "" +"checksum smoltcp 0.4.0 (git+https://github.com/redox-os/smoltcp.git)" = "" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" diff --git a/Cargo.toml b/Cargo.toml index f838a1c8b0..1b5fa8329e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,22 +2,6 @@ name = "redox_netstack" version = "0.1.0" -[[bin]] -name = "ethernetd" -path = "src/ethernetd/main.rs" - -[[bin]] -name = "ipd" -path = "src/ipd/main.rs" - -[[bin]] -name = "tcpd" -path = "src/tcpd/main.rs" - -[[bin]] -name = "udpd" -path = "src/udpd/main.rs" - [[bin]] name = "icmpd" path = "src/icmpd/main.rs" @@ -38,6 +22,6 @@ default-features = false features = ["release_max_level_off"] [dependencies.smoltcp] -git = "https://github.com/m-labs/smoltcp.git" +git = "https://github.com/redox-os/smoltcp.git" default-features = false -features = ["std", "log", "proto-raw", "proto-udp", "proto-tcp"] +features = ["std", "proto-raw", "proto-udp", "proto-tcp"] diff --git a/src/ethernetd/main.rs b/src/ethernetd/main.rs deleted file mode 100644 index c6e6efa008..0000000000 --- a/src/ethernetd/main.rs +++ /dev/null @@ -1,112 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate syscall; - -use event::EventQueue; -use std::cell::RefCell; -use std::fs::File; -use std::io::{Result, Read, Write}; -use std::os::unix::io::{RawFd, FromRawFd}; -use std::process; -use std::rc::Rc; - -use syscall::{Packet, SchemeMut, EWOULDBLOCK}; - -use scheme::EthernetScheme; - -mod scheme; - -fn daemon(network_fd: RawFd, socket_fd: RawFd) { - let network = unsafe { File::from_raw_fd(network_fd) }; - let socket = Rc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd) })); - let scheme = Rc::new(RefCell::new(EthernetScheme::new(network))); - let todo = Rc::new(RefCell::new(Vec::::new())); - - let mut event_queue = EventQueue::<()>::new().expect("ethernetd: failed to create event queue"); - - let socket_net = socket.clone(); - let scheme_net = scheme.clone(); - let todo_net = todo.clone(); - event_queue.add(network_fd, move |_count: usize| -> Result> { - if scheme_net.borrow_mut().input()? > 0 { - let mut todo = todo_net.borrow_mut(); - let mut i = 0; - while i < todo.len() { - let a = todo[i].a; - scheme_net.borrow_mut().handle(&mut todo[i]); - if todo[i].a == (-EWOULDBLOCK) as usize { - todo[i].a = a; - i += 1; - } else { - socket_net.borrow_mut().write(&mut todo[i])?; - todo.remove(i); - } - } - - for (id, handle) in scheme_net.borrow_mut().handles.iter() { - if let Some(frame) = handle.frames.get(0) { - socket_net.borrow_mut().write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: syscall::flag::EVENT_READ, - d: frame.data.len() - })?; - } - } - } - Ok(None) - }).expect("ethernetd: failed to listen for network events"); - - event_queue.add(socket_fd, move |_count: usize| -> Result> { - loop { - let mut packet = Packet::default(); - if socket.borrow_mut().read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - scheme.borrow_mut().handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - todo.borrow_mut().push(packet); - } else { - socket.borrow_mut().write(&mut packet)?; - } - } - - Ok(None) - }).expect("ethernetd: failed to listen for scheme events"); - - event_queue.trigger_all(0).expect("ethernetd: failed to trigger events"); - - event_queue.run().expect("ethernetd: failed to run event loop"); -} - -fn main() { - println!("ethernetd: opening network:"); - match syscall::open("network:", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(network_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - println!("ethernetd: providing ethernet:"); - match syscall::open(":ethernet", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(socket_fd) => { - daemon(network_fd as RawFd, socket_fd as RawFd); - }, - Err(err) => { - println!("ethernetd: failed to create ethernet scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("ethernetd: failed to open network: {}", err); - process::exit(1); - } - } -} diff --git a/src/ethernetd/scheme.rs b/src/ethernetd/scheme.rs deleted file mode 100644 index 1286d9e5e4..0000000000 --- a/src/ethernetd/scheme.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::collections::{BTreeMap, VecDeque}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::os::unix::io::AsRawFd; -use std::{cmp, str, u16}; - -use netutils::{getcfg, MacAddr, EthernetII}; -use syscall; -use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EIO, EWOULDBLOCK}; -use syscall::flag::O_NONBLOCK; -use syscall::scheme::SchemeMut; - -#[derive(Clone)] -pub struct Handle { - /// The flags this handle was opened with - flags: usize, - /// The Host's MAC address - pub host_addr: MacAddr, - /// The ethernet type - pub ethertype: u16, - /// The data - pub frames: VecDeque, -} - -pub struct EthernetScheme { - network: File, - next_id: usize, - pub handles: BTreeMap -} - -impl EthernetScheme { - pub fn new(network: File) -> EthernetScheme { - EthernetScheme { - network: network, - next_id: 1, - handles: BTreeMap::new(), - } - } - - //TODO: Minimize allocation - //TODO: Reduce iteration cost (use BTreeMap of ethertype to handle?) - pub fn input(&mut self) -> io::Result { - 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()); - } - } - total += count; - } - } - Ok(total) - } -} - -impl SchemeMut for EthernetScheme { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let mac_str = getcfg("mac").map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - let mac_addr = MacAddr::from_str(mac_str.trim()); - let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL)))); - - 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) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&mut self, id: usize, buf: &[u8]) -> Result { - if ! buf.is_empty() { - return Err(Error::new(EINVAL)); - } - - 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 { - let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - if let Some(frame) = handle.frames.pop_front() { - let data = frame.to_bytes(); - for (b, d) in buf.iter_mut().zip(data.iter()) { - *b = *d; - } - - Ok(cmp::min(buf.len(), data.len())) - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&mut self, id: usize, buf: &[u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - if let Some(mut frame) = EthernetII::from_bytes(buf) { - frame.header.src = handle.host_addr; - frame.header.ethertype.set(handle.ethertype); - self.network.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Err(Error::new(EINVAL)) - } - } - - fn fevent(&mut self, id: usize, _flags: usize) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - Ok(id) - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - let path_string = format!("ethernet:{:X}", handle.ethertype); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, id: usize) -> Result { - let _handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - syscall::fsync(self.network.as_raw_fd() as usize) - } - - fn close(&mut self, id: usize) -> Result { - let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?; - - drop(handle); - - Ok(0) - } -} diff --git a/src/ipd/interface/ethernet.rs b/src/ipd/interface/ethernet.rs deleted file mode 100644 index 28e561bc66..0000000000 --- a/src/ipd/interface/ethernet.rs +++ /dev/null @@ -1,155 +0,0 @@ -use netutils::{getcfg, n16, Ipv4Addr, MacAddr, Ipv4, EthernetII, EthernetIIHeader, Arp}; -use std::collections::BTreeMap; -use std::fs::File; -use std::io::{Result, Read, Write}; -use std::os::unix::io::{RawFd, FromRawFd}; - -use interface::Interface; - -pub struct EthernetInterface { - mac: MacAddr, - ip: Ipv4Addr, - router: Ipv4Addr, - subnet: Ipv4Addr, - arp_file: File, - ip_file: File, - arp: BTreeMap, - rarp: BTreeMap, -} - -impl EthernetInterface { - pub fn new(arp_fd: RawFd, ip_fd: RawFd) -> Self { - EthernetInterface { - mac: MacAddr::from_str(&getcfg("mac").unwrap().trim()), - ip: Ipv4Addr::from_str(&getcfg("ip").unwrap().trim()), - router: Ipv4Addr::from_str(&getcfg("ip_router").unwrap().trim()), - subnet: Ipv4Addr::from_str(&getcfg("ip_subnet").unwrap().trim()), - arp_file: unsafe { File::from_raw_fd(arp_fd) }, - ip_file: unsafe { File::from_raw_fd(ip_fd) }, - arp: BTreeMap::new(), - rarp: BTreeMap::new(), - } - } -} - -impl Interface for EthernetInterface { - fn ip(&self) -> Ipv4Addr { - self.ip - } - - fn routable(&self, dst: Ipv4Addr) -> bool { - dst != Ipv4Addr::LOOPBACK - } - - fn arp_event(&mut self) -> Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.arp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { - if let Some(packet) = Arp::from_bytes(&frame.data) { - if packet.header.oper.get() == 1 { - if packet.header.dst_ip == self.ip { - if packet.header.src_ip != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - self.arp.insert(packet.header.src_ip, frame.header.src); - self.rarp.insert(frame.header.src, packet.header.src_ip); - } - - let mut response = Arp { - header: packet.header, - data: packet.data.clone(), - }; - response.header.oper.set(2); - response.header.dst_mac = packet.header.src_mac; - response.header.dst_ip = packet.header.src_ip; - response.header.src_mac = self.mac; - response.header.src_ip = self.ip; - - let mut response_frame = EthernetII { - header: frame.header, - data: response.to_bytes() - }; - - response_frame.header.dst = response_frame.header.src; - response_frame.header.src = self.mac; - - self.arp_file.write(&response_frame.to_bytes())?; - } - } - } - } - } - - Ok(()) - } - - fn recv(&mut self) -> Result> { - let mut ips = Vec::new(); - - loop { - let mut bytes = [0; 65536]; - let count = self.ip_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { - if let Some(ip) = Ipv4::from_bytes(&frame.data) { - if ip.header.dst == self.ip || ip.header.dst == Ipv4Addr::BROADCAST { - //TODO: Handle ping here - - if ip.header.src != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - self.arp.insert(ip.header.src, frame.header.src); - self.rarp.insert(frame.header.src, ip.header.src); - } - - ips.push(ip); - } - } - } - } - - Ok(ips) - } - - fn send(&mut self, ip: Ipv4) -> Result { - let mut dst = MacAddr::BROADCAST; - if ip.header.dst != Ipv4Addr::BROADCAST { - let mut needs_routing = false; - - for octet in 0..4 { - let me = self.ip.bytes[octet]; - let mask = self.subnet.bytes[octet]; - let them = ip.header.dst.bytes[octet]; - if me & mask != them & mask { - needs_routing = true; - break; - } - } - - let route_addr = if needs_routing { - self.router - } else { - ip.header.dst - }; - - if let Some(mac) = self.arp.get(&route_addr) { - dst = *mac; - } else { - println!("ipd: need to arp {}", route_addr.to_string()); - } - } - - let frame = EthernetII { - header: EthernetIIHeader { - dst: dst, - src: self.mac, - ethertype: n16::new(0x800), - }, - data: ip.to_bytes() - }; - - self.ip_file.write(&frame.to_bytes()) - } -} diff --git a/src/ipd/interface/loopback.rs b/src/ipd/interface/loopback.rs deleted file mode 100644 index a957ef8818..0000000000 --- a/src/ipd/interface/loopback.rs +++ /dev/null @@ -1,50 +0,0 @@ -use netutils::{Ipv4Addr, Ipv4}; -use std::io::Result; - -use interface::Interface; - -pub struct LoopbackInterface { - packets: Vec -} - -impl LoopbackInterface { - pub fn new() -> Self { - LoopbackInterface { - packets: Vec::new() - } - } -} - -impl Interface for LoopbackInterface { - fn ip(&self) -> Ipv4Addr { - Ipv4Addr::LOOPBACK - } - - fn routable(&self, dst: Ipv4Addr) -> bool { - dst == Ipv4Addr::LOOPBACK - } - - fn recv(&mut self) -> Result> { - let mut ips = Vec::new(); - - for ip in self.packets.drain(..) { - ips.push(ip); - } - - Ok(ips) - } - - fn send(&mut self, ip: Ipv4) -> Result { - self.packets.push(ip); - - Ok(0) - } - - fn arp_event(&mut self) -> Result<()> { - Ok(()) - } - - fn has_loopback_data(&self) -> bool { - ! self.packets.is_empty() - } -} diff --git a/src/ipd/interface/mod.rs b/src/ipd/interface/mod.rs deleted file mode 100644 index 2fa89d9d2e..0000000000 --- a/src/ipd/interface/mod.rs +++ /dev/null @@ -1,19 +0,0 @@ -use netutils::{Ipv4, Ipv4Addr}; -use std::io::Result; - -pub use self::ethernet::EthernetInterface; -pub use self::loopback::LoopbackInterface; - -mod ethernet; -mod loopback; - -pub trait Interface { - fn ip(&self) -> Ipv4Addr; - fn routable(&self, dst: Ipv4Addr) -> bool; - fn recv(&mut self) -> Result>; - fn send(&mut self, ip: Ipv4) -> Result; - - fn arp_event(&mut self) -> Result<()>; - - fn has_loopback_data(&self) -> bool { false } -} diff --git a/src/ipd/main.rs b/src/ipd/main.rs deleted file mode 100644 index 43b3909338..0000000000 --- a/src/ipd/main.rs +++ /dev/null @@ -1,348 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate syscall; - -use event::EventQueue; -use netutils::{Ipv4Addr, Ipv4}; -use netutils::tcp::Tcp; -use std::cell::RefCell; -use std::collections::{BTreeMap, VecDeque}; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::os::unix::io::{RawFd, FromRawFd}; -use std::{process, slice, str}; -use std::rc::Rc; -use syscall::data::Packet; -use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EIO, EINVAL, ENOENT, EWOULDBLOCK}; -use syscall::flag::{EVENT_READ, O_NONBLOCK}; -use syscall::scheme::SchemeMut; - -use interface::{Interface, EthernetInterface, LoopbackInterface}; - -mod interface; - -struct Handle { - proto: u8, - flags: usize, - events: usize, - data: VecDeque>, - todo: VecDeque, -} - -struct Ipd { - scheme_file: File, - interfaces: Vec>, - next_id: usize, - handles: BTreeMap, -} - -impl Ipd { - fn new(scheme_file: File) -> Self { - Ipd { - scheme_file: scheme_file, - interfaces: Vec::new(), - next_id: 1, - handles: BTreeMap::new(), - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - handle.todo.push_back(packet); - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn ip_event(&mut self, if_id: usize) -> io::Result<()> { - if let Some(mut interface) = self.interfaces.get_mut(if_id) { - for ip in interface.recv()? { - for (id, handle) in self.handles.iter_mut() { - if ip.header.proto == handle.proto { - handle.data.push_back(ip.to_bytes()); - - while ! handle.todo.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - let data = handle.data.pop_front().unwrap(); - - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - packet.a = i; - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(data) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: data.len() - })?; - } - } - } - } - } - } - - Ok(()) - } - - fn loopback_event(&mut self, loopback_id: usize) -> io::Result<()> { - let handle_loopback = if let Some(interface) = self.interfaces.get(loopback_id) { - interface.has_loopback_data() - } else { - false - }; - - if handle_loopback { - self.ip_event(loopback_id)?; - } - - Ok(()) - } -} - -impl SchemeMut for Ipd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - if uid == 0 { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let proto = u8::from_str_radix(path, 16).or(Err(Error::new(ENOENT)))?; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle { - proto: proto, - flags: flags, - events: 0, - data: VecDeque::new(), - todo: VecDeque::new(), - }); - - Ok(id) - } else { - Err(Error::new(EACCES)) - } - } - - fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - if ! buf.is_empty() { - return Err(Error::new(EINVAL)); - } - - let handle = { - let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - Handle { - proto: handle.proto, - flags: handle.flags, - events: 0, - data: handle.data.clone(), - todo: VecDeque::new(), - } - }; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - if let Some(data) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - - Ok(i) - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - Ok(0) - } else { - Err(Error::new(EWOULDBLOCK)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - if let Some(mut ip) = Ipv4::from_bytes(buf) { - for mut interface in self.interfaces.iter_mut() { - let if_ip = interface.ip(); - if ip.header.src == if_ip || (ip.header.src == Ipv4Addr::NULL && interface.routable(ip.header.dst)) { - ip.header.src = if_ip; - ip.header.proto = handle.proto; - - if let Some(mut tcp) = Tcp::from_bytes(&ip.data) { - tcp.checksum(&ip.header.src, &ip.header.dst); - ip.data = tcp.to_bytes(); - } - - ip.checksum(); - - interface.send(ip).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - return Ok(buf.len()); - } - } - - Err(Error::new(EADDRNOTAVAIL)) - } else { - Err(Error::new(EINVAL)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?; - - handle.events = flags; - - Ok(file) - } - - fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result { - let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?; - - let path_string = format!("ip:{:X}", handle.proto); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?; - - drop(handle); - - Ok(0) - } -} - -fn daemon(arp_fd: RawFd, ip_fd: RawFd, scheme_fd: RawFd) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - - let ipd = Rc::new(RefCell::new(Ipd::new(scheme_file))); - - let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue"); - - //TODO: Multiple interfaces - { - let if_id = { - let mut ipd = ipd.borrow_mut(); - let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(EthernetInterface::new(arp_fd, ip_fd))); - if_id - }; - - let arp_ipd = ipd.clone(); - event_queue.add(arp_fd, move |_count: usize| -> io::Result> { - if let Some(mut interface) = arp_ipd.borrow_mut().interfaces.get_mut(if_id) { - interface.arp_event()?; - } - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:806"); - - let ip_ipd = ipd.clone(); - event_queue.add(ip_fd, move |_count: usize| -> io::Result> { - ip_ipd.borrow_mut().ip_event(if_id)?; - - Ok(None) - }).expect("ipd: failed to listen to events on ethernet:800"); - } - - let loopback_id = { - let mut ipd = ipd.borrow_mut(); - let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Box::new(LoopbackInterface::new())); - if_id - }; - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - let mut ipd = ipd.borrow_mut(); - - ipd.loopback_event(loopback_id)?; - ipd.scheme_event()?; - ipd.loopback_event(loopback_id)?; - - Ok(None) - }).expect("ipd: failed to listen to events on :ip"); - - // Make sure that all descriptors are at EOF - event_queue.trigger_all(0).expect("ipd: failed to trigger event queue"); - - event_queue.run().expect("ipd: failed to run event queue"); -} - -fn main() { - println!("ipd: opening ethernet:806"); - match syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(arp_fd) => match syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK) { - Ok(ip_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - println!("ipd: providing ip:"); - match syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(arp_fd as RawFd, ip_fd as RawFd, scheme_fd as RawFd); - }, - Err(err) => { - println!("ipd: failed to create ip scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("ipd: failed to open ethernet:800: {}", err); - process::exit(1); - } - }, - Err(err) => { - println!("ipd: failed to open ethernet:806: {}", err); - process::exit(1); - } - } -} diff --git a/src/tcpd/main.rs b/src/tcpd/main.rs deleted file mode 100644 index fb11257778..0000000000 --- a/src/tcpd/main.rs +++ /dev/null @@ -1,982 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate rand; -extern crate syscall; - -use rand::{Rng, OsRng}; -use std::collections::{BTreeMap, VecDeque}; -use std::cell::RefCell; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::{mem, process, slice, str}; -use std::ops::{Deref, DerefMut}; -use std::os::unix::io::{RawFd, FromRawFd}; -use std::rc::Rc; - -use event::EventQueue; -use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Checksum}; -use netutils::tcp::{Tcp, TcpHeader, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK}; -use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; -use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; -use syscall::scheme::SchemeMut; - -fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { - let mut secs = a.tv_sec + b.tv_sec; - - let mut nsecs = a.tv_nsec + b.tv_nsec; - while nsecs >= 1000000000 { - nsecs -= 1000000000; - secs += 1; - } - - TimeSpec { - tv_sec: secs, - tv_nsec: nsecs - } -} - -fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { - let mut socket_parts = socket.split(":"); - let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); - let port = socket_parts.next().unwrap_or("").parse::().unwrap_or(0); - (host, port) -} - -#[derive(Debug)] -struct EmptyHandle { - privileged: bool, - flags: usize -} - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -enum State { - Listen, - SynSent, - SynReceived, - Established, - FinWait1, - FinWait2, - CloseWait, - Closing, - LastAck, - TimeWait, - Closed -} - -#[derive(Debug)] -struct TcpHandle { - local: (Ipv4Addr, u16), - remote: (Ipv4Addr, u16), - flags: usize, - events: usize, - read_timeout: Option, - write_timeout: Option, - ttl: u8, - state: State, - seq: u32, - ack: u32, - data: VecDeque<(Ipv4, Tcp)>, - todo_dup: VecDeque, - todo_read: VecDeque<(Option, Packet)>, - todo_write: VecDeque<(Option, Packet)>, -} - -impl TcpHandle { - fn is_connected(&self) -> bool { - self.remote.0 != Ipv4Addr::NULL && self.remote.1 != 0 - } - - fn read_closed(&self) -> bool { - self.state == State::CloseWait || self.state == State::LastAck || self.state == State::TimeWait || self.state == State::Closed - } - - fn matches(&self, ip: &Ipv4, tcp: &Tcp) -> bool { - // Local address not set or IP dst matches or is broadcast - (self.local.0 == Ipv4Addr::NULL || ip.header.dst == self.local.0 || ip.header.dst == Ipv4Addr::BROADCAST) - // Local port matches UDP dst - && tcp.header.dst.get() == self.local.1 - // Remote address not set or is broadcast, or IP src matches - && (self.remote.0 == Ipv4Addr::NULL || self.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == self.remote.0) - // Remote port not set or UDP src matches - && (self.remote.1 == 0 || tcp.header.src.get() == self.remote.1) - } - - fn create_tcp(&self, flags: u16, data: Vec) -> Tcp { - Tcp { - header: TcpHeader { - src: n16::new(self.local.1), - dst: n16::new(self.remote.1), - sequence: n32::new(self.seq), - ack_num: n32::new(self.ack), - flags: n16::new(((mem::size_of::() << 10) & 0xF000) as u16 | (flags & 0xFFF)), - window_size: n16::new(8192), - checksum: Checksum { data: 0 }, - urgent_pointer: n16::new(0), - }, - options: Vec::new(), - data: data - } - } - - fn create_ip(&self, id: u16, data: Vec) -> Ipv4 { - Ipv4 { - header: Ipv4Header { - ver_hlen: 0x45, - services: 0, - len: n16::new((data.len() + mem::size_of::()) as u16), - id: n16::new(id), - flags_fragment: n16::new(0), - ttl: self.ttl, - proto: 0x06, - checksum: Checksum { data: 0 }, - src: self.local.0, - dst: self.remote.0 - }, - options: Vec::new(), - data: data - } - } -} - -#[derive(Copy, Clone, Debug)] -enum SettingKind { - Ttl, - ReadTimeout, - WriteTimeout -} - -#[derive(Debug)] -enum Handle { - Empty(EmptyHandle), - Tcp(TcpHandle), - Setting(usize, SettingKind), -} - -struct Tcpd { - scheme_file: File, - tcp_file: File, - time_file: File, - ports: BTreeMap, - next_id: usize, - handles: BTreeMap, - rng: OsRng, -} - -impl Tcpd { - fn new(scheme_file: File, tcp_file: File, time_file: File) -> Self { - Tcpd { - scheme_file: scheme_file, - tcp_file: tcp_file, - time_file: time_file, - ports: BTreeMap::new(), - next_id: 1, - handles: BTreeMap::new(), - rng: OsRng::new().expect("tcpd: failed to open RNG") - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - if let Handle::Tcp(ref mut handle) = *handle { - match a { - syscall::number::SYS_DUP => { - packet.a = a; - handle.todo_dup.push_back(packet); - }, - syscall::number::SYS_READ => { - packet.a = a; - - let timeout = match handle.read_timeout { - Some(read_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &read_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }; - - handle.todo_read.push_back((timeout, packet)); - }, - syscall::number::SYS_WRITE => { - packet.a = a; - - let timeout = match handle.write_timeout { - Some(write_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &write_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }; - - handle.todo_write.push_back((timeout, packet)); - }, - _ => { - self.scheme_file.write(&packet)?; - } - } - } - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn tcp_event(&mut self) -> io::Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.tcp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) { - if let Some(tcp) = Tcp::from_bytes(&ip.data) { - let mut closing = Vec::new(); - let mut found_connection = false; - for (id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - if handle.state != State::Listen && handle.matches(&ip, &tcp) { - found_connection = true; - - match handle.state { - State::SynReceived => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - }, - State::SynSent => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Established; - handle.ack = tcp.header.sequence.get() + 1; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - }, - State::Established => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get(); - - if ! tcp.data.is_empty() { - handle.data.push_back((ip.clone(), tcp.clone())); - handle.ack += tcp.data.len() as u32; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - } else if tcp.header.flags.get() & TCP_FIN == TCP_FIN { - handle.state = State::CloseWait; - - handle.ack += 1; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - } - }, - //TODO: Time wait - State::FinWait1 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; - - if tcp.header.flags.get() & TCP_FIN == TCP_FIN { - handle.state = State::TimeWait; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - closing.push(*id); - } else { - handle.state = State::FinWait2; - } - }, - State::FinWait2 => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK | TCP_FIN) == TCP_ACK | TCP_FIN && tcp.header.ack_num.get() == handle.seq { - handle.ack = tcp.header.sequence.get() + 1; - - handle.state = State::TimeWait; - - let tcp = handle.create_tcp(TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - closing.push(*id); - }, - State::LastAck => if tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK && tcp.header.ack_num.get() == handle.seq { - handle.state = State::Closed; - closing.push(*id); - }, - _ => () - } - - while ! handle.todo_read.is_empty() && (! handle.data.is_empty() || handle.read_closed()) { - let (_timeout, mut packet) = handle.todo_read.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - if let Some((ip, mut tcp)) = handle.data.pop_front() { - let len = std::cmp::min(buf.len(), tcp.data.len()); - for (i, c) in tcp.data.drain(0..len).enumerate() { - buf[i] = c; - } - if !tcp.data.is_empty() { - handle.data.push_front((ip, tcp)); - } - packet.a = len; - } else { - packet.a = 0; - } - - self.scheme_file.write(&packet)?; - } - - if ! handle.todo_write.is_empty() && handle.state == State::Established { - let (_timeout, mut packet) = handle.todo_write.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }; - - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - let result = self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))); - if result.is_ok() { - handle.seq += buf.len() as u32; - } - packet.a = Error::mux(result.and(Ok(buf.len()))); - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(&(ref _ip, ref tcp)) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: tcp.data.len() - })?; - } - } - } - } - } - - for file in closing { - if let Handle::Tcp(handle) = self.handles.remove(&file).unwrap() { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); - } - } - } - - if ! found_connection && tcp.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN { - let mut new_handles = Vec::new(); - - for (id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - if handle.state == State::Listen && handle.matches(&ip, &tcp) { - handle.data.push_back((ip.clone(), tcp.clone())); - - while ! handle.todo_dup.is_empty() && ! handle.data.is_empty() { - let mut packet = handle.todo_dup.pop_front().unwrap(); - let (ip, tcp) = handle.data.pop_front().unwrap(); - - let mut new_handle = TcpHandle { - local: handle.local, - remote: (ip.header.src, tcp.header.src.get()), - flags: handle.flags, - events: 0, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - ttl: handle.ttl, - state: State::SynReceived, - seq: self.rng.gen(), - ack: tcp.header.sequence.get() + 1, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes())?; - - new_handle.seq += 1; - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false - } else { - true - } - }); - - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - } - - let id = self.next_id; - self.next_id += 1; - - packet.a = id; - - new_handles.push((packet, Handle::Tcp(new_handle))); - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(&(ref _ip, ref tcp)) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: tcp.data.len() - })?; - } - } - } - } - } - - for (packet, new_handle) in new_handles { - self.handles.insert(packet.a, new_handle); - self.scheme_file.write(&packet)?; - } - } - } - } - } - - Ok(()) - } - - fn time_event(&mut self) -> io::Result<()> { - let mut time = TimeSpec::default(); - if self.time_file.read(&mut time)? < mem::size_of::() { - return Err(io::Error::from_raw_os_error(EINVAL)); - } - - for (_id, handle) in self.handles.iter_mut() { - if let Handle::Tcp(ref mut handle) = *handle { - let mut i = 0; - while i < handle.todo_read.len() { - if let Some(timeout) = handle.todo_read.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo_read.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - - let mut i = 0; - while i < handle.todo_write.len() { - if let Some(timeout) = handle.todo_write.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo_write.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - } - } - - Ok(()) - } - - fn inner_dup(&mut self, file: usize, path: &str) -> Result { - Ok(match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Empty(ref handle) => { - if path.is_empty() { - Handle::Empty(EmptyHandle { - privileged: handle.privileged, - flags: handle.flags - }) - } else { - let mut parts = path.split("/"); - let remote = parse_socket(parts.next().unwrap_or("")); - let mut local = parse_socket(parts.next().unwrap_or("")); - - if local.1 == 0 { - local.1 = self.rng.gen_range(32768, 65535); - } - - if local.1 <= 1024 && ! handle.privileged { - return Err(Error::new(EACCES)); - } - - if self.ports.contains_key(&local.1) { - return Err(Error::new(EADDRINUSE)); - } - - let mut new_handle = TcpHandle { - local: local, - remote: remote, - flags: handle.flags, - events: 0, - read_timeout: None, - write_timeout: None, - ttl: 64, - state: State::Listen, - seq: 0, - ack: 0, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - if new_handle.is_connected() { - new_handle.seq = self.rng.gen(); - new_handle.ack = 0; - new_handle.state = State::SynSent; - - let tcp = new_handle.create_tcp(TCP_SYN, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - new_handle.seq += 1; - } - - self.ports.insert(new_handle.local.1, 1); - - Handle::Tcp(new_handle) - } - }, - Handle::Tcp(ref mut handle) => { - let mut new_handle = TcpHandle { - local: handle.local, - remote: handle.remote, - flags: handle.flags, - events: 0, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - ttl: handle.ttl, - state: handle.state, - seq: handle.seq, - ack: handle.ack, - data: VecDeque::new(), - todo_dup: VecDeque::new(), - todo_read: VecDeque::new(), - todo_write: VecDeque::new(), - }; - - if path == "ttl" { - Handle::Setting(file, SettingKind::Ttl) - } else if path == "read_timeout" { - Handle::Setting(file, SettingKind::ReadTimeout) - } else if path == "write_timeout" { - Handle::Setting(file, SettingKind::WriteTimeout) - } else if path == "listen" { - if handle.is_connected() { - return Err(Error::new(EISCONN)); - } else if let Some((ip, tcp)) = handle.data.pop_front() { - new_handle.remote = (ip.header.src, tcp.header.src.get()); - - new_handle.seq = self.rng.gen(); - new_handle.ack = tcp.header.sequence.get() + 1; - new_handle.state = State::SynReceived; - - let tcp = new_handle.create_tcp(TCP_SYN | TCP_ACK, Vec::new()); - let ip = new_handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - new_handle.seq += 1; - } else { - return Err(Error::new(EWOULDBLOCK)); - } - - handle.data.retain(|&(ref ip, ref tcp)| { - if new_handle.matches(ip, tcp) { - false - } else { - true - } - }); - - Handle::Tcp(new_handle) - } else if path.is_empty() { - new_handle.data = handle.data.clone(); - - Handle::Tcp(new_handle) - } else { - return Err(Error::new(EINVAL)); - } - }, - Handle::Setting(file, kind) => { - Handle::Setting(file, kind) - } - }) - } -} - -impl SchemeMut for Tcpd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle::Empty(EmptyHandle { - privileged: uid == 0, - flags: flags - })); - - match self.inner_dup(id, path) { - Ok(handle) => { - self.handles.insert(id, handle); - Ok(id) - }, - Err(err) => { - self.handles.remove(&id); - Err(err) - } - } - } - - fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; - - let handle = self.inner_dup(file, path)?; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Empty(ref _handle) => { - return Err(Error::new(EBADF)); - }, - Handle::Tcp(ref mut handle) => { - if ! handle.is_connected() { - return Err(Error::new(ENOTCONN)); - } else if let Some((ip, mut tcp)) = handle.data.pop_front() { - let len = std::cmp::min(buf.len(), tcp.data.len()); - for (i, c) in tcp.data.drain(0..len).enumerate() { - buf[i] = c; - } - if !tcp.data.is_empty() { - handle.data.push_front((ip, tcp)); - } - - return Ok(len); - } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() { - return Ok(0); - } else { - return Err(Error::new(EWOULDBLOCK)); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { - if let Some(ref timespec) = *timeout { - timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(mut ttl) = buf.get_mut(0) { - *ttl = handle.ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - get_timeout(&handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - get_timeout(&handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Empty(ref _handle) => { - return Err(Error::new(EBADF)); - }, - Handle::Tcp(ref mut handle) => { - if ! handle.is_connected() { - return Err(Error::new(ENOTCONN)); - } else if buf.len() >= 65507 { - return Err(Error::new(EMSGSIZE)); - } else { - match handle.state { - State::Established => { - let tcp = handle.create_tcp(TCP_ACK | TCP_PSH, buf.to_vec()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - handle.seq += buf.len() as u32; - return Ok(buf.len()); - }, - _ => { - return Err(Error::new(EWOULDBLOCK)); - } - } - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { - if buf.len() >= mem::size_of::() { - let mut timespec = TimeSpec::default(); - let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - *timeout = Some(timespec); - Ok(count) - } else { - *timeout = None; - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(ttl) = buf.get(0) { - handle.ttl = *ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - set_timeout(&mut handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - set_timeout(&mut handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result { - match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Empty(ref mut handle) => { - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - }, - Handle::Tcp(ref mut handle) => { - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } - _ => Err(Error::new(EBADF)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.events = flags; - Ok(file) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, file: usize, buf: &mut [u8]) -> Result { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let path_string = format!("tcp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } else { - Err(Error::new(EBADF)) - } - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let closed = { - if let Handle::Tcp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.data.clear(); - - match handle.state { - State::SynReceived | State::Established => { - handle.state = State::FinWait1; - - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - handle.seq += 1; - - false - }, - State::CloseWait => { - handle.state = State::LastAck; - - let tcp = handle.create_tcp(TCP_FIN | TCP_ACK, Vec::new()); - let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes()); - self.tcp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - - handle.seq += 1; - - false - }, - _ => true - } - } else { - true - } - }; - - if closed { - if let Handle::Tcp(handle) = self.handles.remove(&file).ok_or(Error::new(EBADF))? { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - self.ports.remove(&handle.local.1); - } - } - } - - Ok(0) - } -} - -fn daemon(scheme_fd: RawFd, tcp_fd: RawFd, time_fd: RawFd) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - let tcp_file = unsafe { File::from_raw_fd(tcp_fd) }; - let time_file = unsafe { File::from_raw_fd(time_fd) }; - - let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file, time_file))); - - let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue"); - - let time_tcpd = tcpd.clone(); - event_queue.add(time_fd, move |_count: usize| -> io::Result> { - time_tcpd.borrow_mut().time_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on time:"); - - let tcp_tcpd = tcpd.clone(); - event_queue.add(tcp_fd, move |_count: usize| -> io::Result> { - tcp_tcpd.borrow_mut().tcp_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on ip:6"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - tcpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("tcpd: failed to listen to events on :tcp"); - - event_queue.trigger_all(0).expect("tcpd: failed to trigger event queue"); - - event_queue.run().expect("tcpd: failed to run event queue"); -} - -fn main() { - let time_path = format!("time:{}", CLOCK_MONOTONIC); - match syscall::open(&time_path, O_RDWR) { - Ok(time_fd) => { - println!("tcpd: opening ip:6"); - match syscall::open("ip:6", O_RDWR | O_NONBLOCK) { - Ok(tcp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - println!("tcpd: providing tcp:"); - match syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(scheme_fd as RawFd, tcp_fd as RawFd, time_fd as RawFd); - }, - Err(err) => { - println!("tcpd: failed to create tcp scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("tcpd: failed to open ip:6: {}", err); - process::exit(1); - } - } - }, - Err(err) => { - println!("tcpd: failed to open {}: {}", time_path, err); - process::exit(1); - } - } -} diff --git a/src/udpd/main.rs b/src/udpd/main.rs deleted file mode 100644 index cfcf4d94d0..0000000000 --- a/src/udpd/main.rs +++ /dev/null @@ -1,588 +0,0 @@ -extern crate event; -extern crate netutils; -extern crate rand; -extern crate syscall; - -use rand::{Rng, OsRng}; -use std::collections::{BTreeMap, VecDeque}; -use std::cell::RefCell; -use std::fs::File; -use std::io::{self, Read, Write}; -use std::{mem, process, slice, str}; -use std::ops::{Deref, DerefMut}; -use std::os::unix::io::{RawFd, FromRawFd}; -use std::rc::Rc; - -use event::EventQueue; -use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Checksum}; -use netutils::udp::{Udp, UdpHeader}; -use syscall::data::{Packet, TimeSpec}; -use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EIO, EINVAL, EMSGSIZE, ENOTCONN, ETIMEDOUT, EWOULDBLOCK}; -use syscall::flag::{CLOCK_MONOTONIC, EVENT_READ, F_GETFL, F_SETFL, O_ACCMODE, O_CREAT, O_RDWR, O_NONBLOCK}; -use syscall::number::{SYS_READ, SYS_WRITE}; -use syscall::scheme::SchemeMut; - -fn add_time(a: &TimeSpec, b: &TimeSpec) -> TimeSpec { - let mut secs = a.tv_sec + b.tv_sec; - - let mut nsecs = a.tv_nsec + b.tv_nsec; - while nsecs >= 1000000000 { - nsecs -= 1000000000; - secs += 1; - } - - TimeSpec { - tv_sec: secs, - tv_nsec: nsecs - } -} - -fn parse_socket(socket: &str) -> (Ipv4Addr, u16) { - let mut socket_parts = socket.split(":"); - let host = Ipv4Addr::from_str(socket_parts.next().unwrap_or("")); - let port = socket_parts.next().unwrap_or("").parse::().unwrap_or(0); - (host, port) -} - -struct UdpHandle { - local: (Ipv4Addr, u16), - remote: (Ipv4Addr, u16), - flags: usize, - events: usize, - read_timeout: Option, - write_timeout: Option, - ttl: u8, - data: VecDeque>, - todo: VecDeque<(Option, Packet)>, -} - -#[derive(Copy, Clone)] -enum SettingKind { - Ttl, - ReadTimeout, - WriteTimeout -} - -enum Handle { - Udp(UdpHandle), - Setting(usize, SettingKind), -} - -struct Udpd { - scheme_file: File, - udp_file: File, - time_file: File, - ports: BTreeMap, - next_id: usize, - handles: BTreeMap, - rng: OsRng, -} - -impl Udpd { - fn new(scheme_file: File, udp_file: File, time_file: File) -> Self { - Udpd { - scheme_file: scheme_file, - udp_file: udp_file, - time_file: time_file, - ports: BTreeMap::new(), - next_id: 1, - handles: BTreeMap::new(), - rng: OsRng::new().expect("udpd: failed to open RNG") - } - } - - fn scheme_event(&mut self) -> io::Result<()> { - loop { - let mut packet = Packet::default(); - if self.scheme_file.read(&mut packet)? == 0 { - break; - } - - let a = packet.a; - self.handle(&mut packet); - if packet.a == (-EWOULDBLOCK) as usize { - packet.a = a; - if let Some(mut handle) = self.handles.get_mut(&packet.b) { - if let Handle::Udp(ref mut handle) = *handle { - let timeout = match packet.a { - SYS_READ => match handle.read_timeout { - Some(read_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &read_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }, - SYS_WRITE => match handle.write_timeout { - Some(write_timeout) => { - let mut time = TimeSpec::default(); - syscall::clock_gettime(CLOCK_MONOTONIC, &mut time).map_err(|err| io::Error::from_raw_os_error(err.errno))?; - - let timeout = add_time(&time, &write_timeout); - self.time_file.write(&timeout)?; - Some(timeout) - }, - None => None - }, - _ => None - }; - - handle.todo.push_back((timeout, packet)); - } - } - } else { - self.scheme_file.write(&packet)?; - } - } - - Ok(()) - } - - fn udp_event(&mut self) -> io::Result<()> { - loop { - let mut bytes = [0; 65536]; - let count = self.udp_file.read(&mut bytes)?; - if count == 0 { - break; - } - if let Some(ip) = Ipv4::from_bytes(&bytes[.. count]) { - if let Some(udp) = Udp::from_bytes(&ip.data) { - for (id, handle) in self.handles.iter_mut() { - if let Handle::Udp(ref mut handle) = *handle { - // Local address not set or IP dst matches or is broadcast - if (handle.local.0 == Ipv4Addr::NULL || ip.header.dst == handle.local.0 || ip.header.dst == Ipv4Addr::BROADCAST) - // Local port matches UDP dst - && udp.header.dst.get() == handle.local.1 - // Remote address not set or is broadcast, or IP src matches - && (handle.remote.0 == Ipv4Addr::NULL || handle.remote.0 == Ipv4Addr::BROADCAST || ip.header.src == handle.remote.0) - // Remote port not set or UDP src matches - && (handle.remote.1 == 0 || udp.header.src.get() == handle.remote.1) - { - handle.data.push_back(udp.data.clone()); - - while ! handle.todo.is_empty() && ! handle.data.is_empty() { - let (_timeout, mut packet) = handle.todo.pop_front().unwrap(); - let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; - let data = handle.data.pop_front().unwrap(); - - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - packet.a = i; - - self.scheme_file.write(&packet)?; - } - - if handle.events & EVENT_READ == EVENT_READ { - if let Some(data) = handle.data.get(0) { - self.scheme_file.write(&Packet { - id: 0, - pid: 0, - uid: 0, - gid: 0, - a: syscall::number::SYS_FEVENT, - b: *id, - c: EVENT_READ, - d: data.len() - })?; - } - } - } - } - } - } - } - } - - Ok(()) - } - - fn time_event(&mut self) -> io::Result<()> { - let mut time = TimeSpec::default(); - if self.time_file.read(&mut time)? < mem::size_of::() { - return Err(io::Error::from_raw_os_error(EINVAL)); - } - - for (_id, handle) in self.handles.iter_mut() { - if let Handle::Udp(ref mut handle) = *handle { - let mut i = 0; - while i < handle.todo.len() { - if let Some(timeout) = handle.todo.get(i).map(|e| e.0.clone()).unwrap_or(None) { - if time.tv_sec > timeout.tv_sec || (time.tv_sec == timeout.tv_sec && time.tv_nsec >= timeout.tv_nsec) { - let (_timeout, mut packet) = handle.todo.remove(i).unwrap(); - packet.a = (-ETIMEDOUT) as usize; - self.scheme_file.write(&packet)?; - } else { - i += 1; - } - } else { - i += 1; - } - } - } - } - - Ok(()) - } -} - -impl SchemeMut for Udpd { - fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { - let path = str::from_utf8(url).or(Err(Error::new(EINVAL)))?; - - let mut parts = path.split("/"); - let remote = parse_socket(parts.next().unwrap_or("")); - let mut local = parse_socket(parts.next().unwrap_or("")); - - if local.1 == 0 { - local.1 = self.rng.gen_range(32768, 65535); - } - - if local.1 <= 1024 && uid != 0 { - return Err(Error::new(EACCES)); - } - - if self.ports.contains_key(&local.1) { - return Err(Error::new(EADDRINUSE)); - } - - self.ports.insert(local.1, 1); - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, Handle::Udp(UdpHandle { - local: local, - remote: remote, - flags: flags, - events: 0, - ttl: 64, - read_timeout: None, - write_timeout: None, - data: VecDeque::new(), - todo: VecDeque::new(), - })); - - Ok(id) - } - - fn dup(&mut self, file: usize, buf: &[u8]) -> Result { - let handle = match *self.handles.get(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref handle) => { - let mut handle = UdpHandle { - local: handle.local, - remote: handle.remote, - flags: handle.flags, - events: 0, - ttl: handle.ttl, - read_timeout: handle.read_timeout, - write_timeout: handle.write_timeout, - data: handle.data.clone(), - todo: VecDeque::new(), - }; - - let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?; - - if path == "ttl" { - Handle::Setting(file, SettingKind::Ttl) - } else if path == "read_timeout" { - Handle::Setting(file, SettingKind::ReadTimeout) - } else if path == "write_timeout" { - Handle::Setting(file, SettingKind::WriteTimeout) - } else { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - handle.remote = parse_socket(path); - } - - if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - } - - Handle::Udp(handle) - } - }, - Handle::Setting(file, kind) => { - Handle::Setting(file, kind) - } - }; - - let id = self.next_id; - self.next_id += 1; - - self.handles.insert(id, handle); - - Ok(id) - } - - fn read(&mut self, file: usize, buf: &mut [u8]) -> Result { - let (file, kind) = match *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref mut handle) => { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - return Err(Error::new(ENOTCONN)); - } else if let Some(data) = handle.data.pop_front() { - let mut i = 0; - while i < buf.len() && i < data.len() { - buf[i] = data[i]; - i += 1; - } - - return Ok(i); - } else if handle.flags & O_NONBLOCK == O_NONBLOCK { - return Ok(0); - } else { - return Err(Error::new(EWOULDBLOCK)); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let get_timeout = |timeout: &Option, buf: &mut [u8]| -> Result { - if let Some(ref timespec) = *timeout { - timespec.deref().read(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))) - } else { - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(mut ttl) = buf.get_mut(0) { - *ttl = handle.ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - get_timeout(&handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - get_timeout(&handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn write(&mut self, file: usize, buf: &[u8]) -> Result { - let (file, kind) = match *self.handles.get(&file).ok_or(Error::new(EBADF))? { - Handle::Udp(ref handle) => { - if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 { - return Err(Error::new(ENOTCONN)); - } else if buf.len() >= 65507 { - return Err(Error::new(EMSGSIZE)); - } else { - let udp_data = buf.to_vec(); - - let udp = Udp { - header: UdpHeader { - src: n16::new(handle.local.1), - dst: n16::new(handle.remote.1), - len: n16::new((udp_data.len() + mem::size_of::()) as u16), - checksum: Checksum { data: 0 } - }, - data: udp_data - }; - - let ip_data = udp.to_bytes(); - - let ip = Ipv4 { - header: Ipv4Header { - ver_hlen: 0x45, - services: 0, - len: n16::new((ip_data.len() + mem::size_of::()) as u16), - id: n16::new(self.rng.gen()), - flags_fragment: n16::new(0), - ttl: handle.ttl, - proto: 0x11, - checksum: Checksum { data: 0 }, - src: handle.local.0, - dst: handle.remote.0 - }, - options: Vec::new(), - data: ip_data - }; - - return self.udp_file.write(&ip.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO))).and(Ok(buf.len())); - } - }, - Handle::Setting(file, kind) => { - (file, kind) - } - }; - - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let set_timeout = |timeout: &mut Option, buf: &[u8]| -> Result { - if buf.len() >= mem::size_of::() { - let mut timespec = TimeSpec::default(); - let count = timespec.deref_mut().write(buf).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; - *timeout = Some(timespec); - Ok(count) - } else { - *timeout = None; - Ok(0) - } - }; - - match kind { - SettingKind::Ttl => { - if let Some(ttl) = buf.get(0) { - handle.ttl = *ttl; - Ok(1) - } else { - Ok(0) - } - }, - SettingKind::ReadTimeout => { - set_timeout(&mut handle.read_timeout, buf) - }, - SettingKind::WriteTimeout => { - set_timeout(&mut handle.write_timeout, buf) - } - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fcntl(&mut self, file: usize, cmd: usize, arg: usize) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - match cmd { - F_GETFL => Ok(handle.flags), - F_SETFL => { - handle.flags = arg & ! O_ACCMODE; - Ok(0) - }, - _ => Err(Error::new(EINVAL)) - } - } else { - Err(Error::new(EBADF)) - } - } - - fn fevent(&mut self, file: usize, flags: usize) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - handle.events = flags; - Ok(file) - } else { - Err(Error::new(EBADF)) - } - } - - fn fpath(&mut self, file: usize, buf: &mut [u8]) -> Result { - if let Handle::Udp(ref mut handle) = *self.handles.get_mut(&file).ok_or(Error::new(EBADF))? { - let path_string = format!("udp:{}:{}/{}:{}", handle.remote.0.to_string(), handle.remote.1, handle.local.0.to_string(), handle.local.1); - let path = path_string.as_bytes(); - - let mut i = 0; - while i < buf.len() && i < path.len() { - buf[i] = path[i]; - i += 1; - } - - Ok(i) - } else { - Err(Error::new(EBADF)) - } - } - - fn fsync(&mut self, file: usize) -> Result { - let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?; - - Ok(0) - } - - fn close(&mut self, file: usize) -> Result { - let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?; - - if let Handle::Udp(ref handle) = handle { - let remove = if let Some(mut port) = self.ports.get_mut(&handle.local.1) { - *port = *port + 1; - *port == 0 - } else { - false - }; - - if remove { - drop(self.ports.remove(&handle.local.1)); - } - } - - drop(handle); - - Ok(0) - } -} -fn daemon(scheme_fd: RawFd, udp_fd: RawFd, time_fd: RawFd) { - let scheme_file = unsafe { File::from_raw_fd(scheme_fd) }; - let udp_file = unsafe { File::from_raw_fd(udp_fd) }; - let time_file = unsafe { File::from_raw_fd(time_fd) }; - - let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file, time_file))); - - let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue"); - - let time_udpd = udpd.clone(); - event_queue.add(time_fd, move |_count: usize| -> io::Result> { - time_udpd.borrow_mut().time_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on time:"); - - let udp_udpd = udpd.clone(); - event_queue.add(udp_fd, move |_count: usize| -> io::Result> { - udp_udpd.borrow_mut().udp_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on ip:11"); - - event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { - udpd.borrow_mut().scheme_event()?; - Ok(None) - }).expect("udpd: failed to listen to events on :udp"); - - event_queue.trigger_all(0).expect("udpd: failed to trigger event queue"); - - event_queue.run().expect("udpd: failed to run event queue"); -} - -fn main() { - let time_path = format!("time:{}", CLOCK_MONOTONIC); - match syscall::open(&time_path, O_RDWR) { - Ok(time_fd) => { - println!("udpd: opening ip:11"); - match syscall::open("ip:11", O_RDWR | O_NONBLOCK) { - Ok(udp_fd) => { - // Daemonize - if unsafe { syscall::clone(0).unwrap() } == 0 { - println!("udpd: providing udp:"); - match syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK) { - Ok(scheme_fd) => { - daemon(scheme_fd as RawFd, udp_fd as RawFd, time_fd as RawFd); - }, - Err(err) => { - println!("udpd: failed to create udp scheme: {}", err); - process::exit(1); - } - } - } - }, - Err(err) => { - println!("udpd: failed to open ip:11: {}", err); - process::exit(1); - } - } - }, - Err(err) => { - println!("udpd: failed to open {}: {}", time_path, err); - process::exit(1); - } - } -}