Redo networking (#22)
* Rewriting network functions * Add buffer to dup Fix non-blocking handling by triggering once on enabling events to read to EOF * Modifications for UDP API * Implement TCP client side * Add active close * Add DMAR parser * Implement basic TCP listening. Need to improve the state machine * Reduce debugging * Fixes for close procedure * Updates to fix path processing in libstd
This commit is contained in:
		
							parent
							
								
									268c859fd6
								
							
						
					
					
						commit
						2491e4771e
					
				
					 54 changed files with 1884 additions and 1476 deletions
				
			
		
							
								
								
									
										10
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
					@ -42,7 +42,6 @@ clean:
 | 
				
			||||||
	cargo clean --manifest-path programs/userutils/Cargo.toml
 | 
						cargo clean --manifest-path programs/userutils/Cargo.toml
 | 
				
			||||||
	cargo clean --manifest-path programs/smith/Cargo.toml
 | 
						cargo clean --manifest-path programs/smith/Cargo.toml
 | 
				
			||||||
	cargo clean --manifest-path programs/tar/Cargo.toml
 | 
						cargo clean --manifest-path programs/tar/Cargo.toml
 | 
				
			||||||
	cargo clean --manifest-path schemes/arpd/Cargo.toml
 | 
					 | 
				
			||||||
	cargo clean --manifest-path schemes/ethernetd/Cargo.toml
 | 
						cargo clean --manifest-path schemes/ethernetd/Cargo.toml
 | 
				
			||||||
	cargo clean --manifest-path schemes/example/Cargo.toml
 | 
						cargo clean --manifest-path schemes/example/Cargo.toml
 | 
				
			||||||
	cargo clean --manifest-path schemes/ipd/Cargo.toml
 | 
						cargo clean --manifest-path schemes/ipd/Cargo.toml
 | 
				
			||||||
| 
						 | 
					@ -92,7 +91,6 @@ update:
 | 
				
			||||||
	cargo update --manifest-path programs/userutils/Cargo.toml
 | 
						cargo update --manifest-path programs/userutils/Cargo.toml
 | 
				
			||||||
	cargo update --manifest-path programs/smith/Cargo.toml
 | 
						cargo update --manifest-path programs/smith/Cargo.toml
 | 
				
			||||||
	cargo update --manifest-path programs/tar/Cargo.toml
 | 
						cargo update --manifest-path programs/tar/Cargo.toml
 | 
				
			||||||
	cargo update --manifest-path schemes/arpd/Cargo.toml
 | 
					 | 
				
			||||||
	cargo update --manifest-path schemes/ethernetd/Cargo.toml
 | 
						cargo update --manifest-path schemes/ethernetd/Cargo.toml
 | 
				
			||||||
	cargo update --manifest-path schemes/example/Cargo.toml
 | 
						cargo update --manifest-path schemes/example/Cargo.toml
 | 
				
			||||||
	cargo update --manifest-path schemes/ipd/Cargo.toml
 | 
						cargo update --manifest-path schemes/ipd/Cargo.toml
 | 
				
			||||||
| 
						 | 
					@ -120,7 +118,12 @@ $(KBUILD)/harddrive.bin: $(KBUILD)/kernel
 | 
				
			||||||
qemu: $(KBUILD)/harddrive.bin
 | 
					qemu: $(KBUILD)/harddrive.bin
 | 
				
			||||||
	$(QEMU) $(QEMUFLAGS) -kernel $<
 | 
						$(QEMU) $(QEMUFLAGS) -kernel $<
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
	QEMUFLAGS+=-machine q35 -smp 4 -m 1024
 | 
						QEMUFLAGS+=-smp 4 -m 1024
 | 
				
			||||||
 | 
						ifeq ($(iommu),no)
 | 
				
			||||||
 | 
							QEMUFLAGS+=-machine q35
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							QEMUFLAGS+=-machine q35,iommu=on
 | 
				
			||||||
 | 
						endif
 | 
				
			||||||
	ifeq ($(net),no)
 | 
						ifeq ($(net),no)
 | 
				
			||||||
		QEMUFLAGS+=-net none
 | 
							QEMUFLAGS+=-net none
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
| 
						 | 
					@ -406,7 +409,6 @@ userutils: \
 | 
				
			||||||
	filesystem/bin/sudo
 | 
						filesystem/bin/sudo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
schemes: \
 | 
					schemes: \
 | 
				
			||||||
	filesystem/bin/arpd \
 | 
					 | 
				
			||||||
	filesystem/bin/ethernetd \
 | 
						filesystem/bin/ethernetd \
 | 
				
			||||||
	filesystem/bin/example \
 | 
						filesystem/bin/example \
 | 
				
			||||||
	filesystem/bin/ipd \
 | 
						filesystem/bin/ipd \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										170
									
								
								arch/x86_64/src/acpi/dmar.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								arch/x86_64/src/acpi/dmar.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,170 @@
 | 
				
			||||||
 | 
					use core::mem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::sdt::Sdt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// The DMA Remapping Table
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct Dmar {
 | 
				
			||||||
 | 
					    sdt: &'static Sdt,
 | 
				
			||||||
 | 
					    pub addr_width: u8,
 | 
				
			||||||
 | 
					    pub flags: u8,
 | 
				
			||||||
 | 
					    _rsv: [u8; 10],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Dmar {
 | 
				
			||||||
 | 
					    pub fn new(sdt: &'static Sdt) -> Option<Dmar> {
 | 
				
			||||||
 | 
					        if &sdt.signature == b"DMAR" && sdt.data_len() >= 12 { //Not valid if no local address and flags
 | 
				
			||||||
 | 
					            let addr_width = unsafe { *(sdt.data_address() as *const u8) };
 | 
				
			||||||
 | 
					            let flags = unsafe { *(sdt.data_address() as *const u8).offset(1) };
 | 
				
			||||||
 | 
					            let rsv: [u8; 10] = unsafe { *((sdt.data_address() as *const u8).offset(2) as *const [u8; 10]) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Some(Dmar {
 | 
				
			||||||
 | 
					                sdt: sdt,
 | 
				
			||||||
 | 
					                addr_width: addr_width,
 | 
				
			||||||
 | 
					                flags: flags,
 | 
				
			||||||
 | 
					                _rsv: rsv,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn iter(&self) -> DmarIter {
 | 
				
			||||||
 | 
					        DmarIter {
 | 
				
			||||||
 | 
					            sdt: self.sdt,
 | 
				
			||||||
 | 
					            i: 12 // Skip address width and flags
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR DMA Remapping Hardware Unit Definition
 | 
				
			||||||
 | 
					// TODO: Implement iterator on DmarDrhd scope
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(packed)]
 | 
				
			||||||
 | 
					pub struct DmarDrhd {
 | 
				
			||||||
 | 
					    kind: u16,
 | 
				
			||||||
 | 
					    length: u16,
 | 
				
			||||||
 | 
					    flags: u8,
 | 
				
			||||||
 | 
					    _rsv: u8,
 | 
				
			||||||
 | 
					    segment: u16,
 | 
				
			||||||
 | 
					    base: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR Reserved Memory Region Reporting
 | 
				
			||||||
 | 
					// TODO: Implement iterator on DmarRmrr scope
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(packed)]
 | 
				
			||||||
 | 
					pub struct DmarRmrr {
 | 
				
			||||||
 | 
					    kind: u16,
 | 
				
			||||||
 | 
					    length: u16,
 | 
				
			||||||
 | 
					    _rsv: u16,
 | 
				
			||||||
 | 
					    segment: u16,
 | 
				
			||||||
 | 
					    base: u64,
 | 
				
			||||||
 | 
					    limit: u64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR Root Port ATS Capability Reporting
 | 
				
			||||||
 | 
					// TODO: Implement iterator on DmarAtsr scope
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(packed)]
 | 
				
			||||||
 | 
					pub struct DmarAtsr {
 | 
				
			||||||
 | 
					    kind: u16,
 | 
				
			||||||
 | 
					    length: u16,
 | 
				
			||||||
 | 
					    flags: u8,
 | 
				
			||||||
 | 
					    _rsv: u8,
 | 
				
			||||||
 | 
					    segment: u16,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR Remapping Hardware Static Affinity
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(packed)]
 | 
				
			||||||
 | 
					pub struct DmarRhsa {
 | 
				
			||||||
 | 
					    kind: u16,
 | 
				
			||||||
 | 
					    length: u16,
 | 
				
			||||||
 | 
					    _rsv: u32,
 | 
				
			||||||
 | 
					    base: u64,
 | 
				
			||||||
 | 
					    domain: u32,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR ACPI Name-space Device Declaration
 | 
				
			||||||
 | 
					// TODO: Implement iterator on DmarAndd object name
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(packed)]
 | 
				
			||||||
 | 
					pub struct DmarAndd {
 | 
				
			||||||
 | 
					    kind: u16,
 | 
				
			||||||
 | 
					    length: u16,
 | 
				
			||||||
 | 
					    _rsv: [u8; 3],
 | 
				
			||||||
 | 
					    acpi_dev: u8,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// DMAR Entries
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub enum DmarEntry {
 | 
				
			||||||
 | 
					    Drhd(&'static DmarDrhd),
 | 
				
			||||||
 | 
					    InvalidDrhd(usize),
 | 
				
			||||||
 | 
					    Rmrr(&'static DmarRmrr),
 | 
				
			||||||
 | 
					    InvalidRmrr(usize),
 | 
				
			||||||
 | 
					    Atsr(&'static DmarAtsr),
 | 
				
			||||||
 | 
					    InvalidAtsr(usize),
 | 
				
			||||||
 | 
					    Rhsa(&'static DmarRhsa),
 | 
				
			||||||
 | 
					    InvalidRhsa(usize),
 | 
				
			||||||
 | 
					    Andd(&'static DmarAndd),
 | 
				
			||||||
 | 
					    InvalidAndd(usize),
 | 
				
			||||||
 | 
					    Unknown(u16)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct DmarIter {
 | 
				
			||||||
 | 
					    sdt: &'static Sdt,
 | 
				
			||||||
 | 
					    i: usize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Iterator for DmarIter {
 | 
				
			||||||
 | 
					    type Item = DmarEntry;
 | 
				
			||||||
 | 
					    fn next(&mut self) -> Option<Self::Item> {
 | 
				
			||||||
 | 
					        if self.i + 4 <= self.sdt.data_len() {
 | 
				
			||||||
 | 
					            let entry_type = unsafe { *((self.sdt.data_address() as *const u8).offset(self.i as isize) as *const u16) };
 | 
				
			||||||
 | 
					            let entry_len = unsafe { *((self.sdt.data_address() as *const u8).offset(self.i as isize + 2) as *const u16) } as usize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.i + entry_len <= self.sdt.data_len() {
 | 
				
			||||||
 | 
					                let item = match entry_type {
 | 
				
			||||||
 | 
					                    0 => if entry_len >= mem::size_of::<DmarDrhd>() {
 | 
				
			||||||
 | 
					                        DmarEntry::Drhd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarDrhd) })
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        DmarEntry::InvalidDrhd(entry_len)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    1 => if entry_len >= mem::size_of::<DmarRmrr>() {
 | 
				
			||||||
 | 
					                        DmarEntry::Rmrr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRmrr) })
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        DmarEntry::InvalidRmrr(entry_len)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    2 => if entry_len >= mem::size_of::<DmarAtsr>() {
 | 
				
			||||||
 | 
					                        DmarEntry::Atsr(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAtsr) })
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        DmarEntry::InvalidAtsr(entry_len)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    3 => if entry_len == mem::size_of::<DmarRhsa>() {
 | 
				
			||||||
 | 
					                        DmarEntry::Rhsa(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarRhsa) })
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        DmarEntry::InvalidRhsa(entry_len)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    4 => if entry_len >= mem::size_of::<DmarAndd>() {
 | 
				
			||||||
 | 
					                        DmarEntry::Andd(unsafe { &*((self.sdt.data_address() + self.i) as *const DmarAndd) })
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        DmarEntry::InvalidAndd(entry_len)
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                    _ => DmarEntry::Unknown(entry_type)
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.i += entry_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Some(item)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                None
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -9,12 +9,14 @@ use memory::{allocate_frames, Frame};
 | 
				
			||||||
use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
 | 
					use paging::{entry, ActivePageTable, Page, PhysicalAddress, VirtualAddress};
 | 
				
			||||||
use start::{kstart_ap, CPU_COUNT, AP_READY};
 | 
					use start::{kstart_ap, CPU_COUNT, AP_READY};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use self::dmar::Dmar;
 | 
				
			||||||
use self::local_apic::LocalApic;
 | 
					use self::local_apic::LocalApic;
 | 
				
			||||||
use self::madt::{Madt, MadtEntry};
 | 
					use self::madt::{Madt, MadtEntry};
 | 
				
			||||||
use self::rsdt::Rsdt;
 | 
					use self::rsdt::Rsdt;
 | 
				
			||||||
use self::sdt::Sdt;
 | 
					use self::sdt::Sdt;
 | 
				
			||||||
use self::xsdt::Xsdt;
 | 
					use self::xsdt::Xsdt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod dmar;
 | 
				
			||||||
pub mod local_apic;
 | 
					pub mod local_apic;
 | 
				
			||||||
pub mod madt;
 | 
					pub mod madt;
 | 
				
			||||||
pub mod rsdt;
 | 
					pub mod rsdt;
 | 
				
			||||||
| 
						 | 
					@ -133,6 +135,12 @@ pub fn init_sdt(sdt: &'static Sdt, active_table: &mut ActivePageTable) {
 | 
				
			||||||
        // Unmap trampoline
 | 
					        // Unmap trampoline
 | 
				
			||||||
        active_table.unmap(trampoline_page);
 | 
					        active_table.unmap(trampoline_page);
 | 
				
			||||||
        active_table.flush(trampoline_page);
 | 
					        active_table.flush(trampoline_page);
 | 
				
			||||||
 | 
					    } else if let Some(dmar) = Dmar::new(sdt) {
 | 
				
			||||||
 | 
					        println!(": {}: {}", dmar.addr_width, dmar.flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for dmar_entry in dmar.iter() {
 | 
				
			||||||
 | 
					            println!("      {:?}", dmar_entry);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        println!(": Unknown");
 | 
					        println!(": Unknown");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,13 +38,43 @@ impl<R> EventQueue<R> {
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Remove a file from the event queue, returning its callback if found
 | 
				
			||||||
 | 
					    pub fn remove(&mut self, fd: RawFd) -> Result<Option<Box<FnMut(usize) -> Result<Option<R>>>>> {
 | 
				
			||||||
 | 
					        if let Some(callback) = self.callbacks.remove(&fd) {
 | 
				
			||||||
 | 
					            syscall::fevent(fd, 0).map_err(|x| Error::from_sys(x))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Ok(Some(callback))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Ok(None)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Send an event to a descriptor callback
 | 
				
			||||||
 | 
					    pub fn trigger(&mut self, fd: RawFd, count: usize) -> Result<Option<R>> {
 | 
				
			||||||
 | 
					        if let Some(callback) = self.callbacks.get_mut(&fd) {
 | 
				
			||||||
 | 
					            callback(count)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Ok(None)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Send an event to all descriptor callbacks, useful for cleaning out buffers after init
 | 
				
			||||||
 | 
					    pub fn trigger_all(&mut self, count: usize) -> Result<Vec<R>> {
 | 
				
			||||||
 | 
					        let mut rets = Vec::new();
 | 
				
			||||||
 | 
					        for (_fd, callback) in self.callbacks.iter_mut() {
 | 
				
			||||||
 | 
					            if let Some(ret) = callback(count)? {
 | 
				
			||||||
 | 
					                rets.push(ret);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(rets)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Process the event queue until a callback returns Some(R)
 | 
					    /// Process the event queue until a callback returns Some(R)
 | 
				
			||||||
    pub fn run(&mut self) -> Result<R> {
 | 
					    pub fn run(&mut self) -> Result<R> {
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let mut event = syscall::Event::default();
 | 
					            let mut event = syscall::Event::default();
 | 
				
			||||||
            self.file.read(&mut event)?;
 | 
					            if self.file.read(&mut event)? > 0 {
 | 
				
			||||||
            if let Some(callback) = self.callbacks.get_mut(&event.id) {
 | 
					                if let Some(ret) = self.trigger(event.id, event.data)? {
 | 
				
			||||||
                if let Some(ret) = callback(event.data)? {
 | 
					 | 
				
			||||||
                    return Ok(ret);
 | 
					                    return Ok(ret);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ use syscall::error::*;
 | 
				
			||||||
pub trait Resource {
 | 
					pub trait Resource {
 | 
				
			||||||
    /// Duplicate the resource
 | 
					    /// Duplicate the resource
 | 
				
			||||||
    /// Returns `EPERM` if the operation is not supported.
 | 
					    /// Returns `EPERM` if the operation is not supported.
 | 
				
			||||||
    fn dup(&self) -> Result<Box<Self>> {
 | 
					    fn dup(&self, _buf: &[u8]) -> Result<Box<Self>> {
 | 
				
			||||||
        Err(Error::new(EPERM))
 | 
					        Err(Error::new(EPERM))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ pub trait ResourceScheme<T: Resource> {
 | 
				
			||||||
            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SYS_DUP => self.dup(packet.b),
 | 
					            SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
				
			||||||
            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
					            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
				
			||||||
            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
					            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
				
			||||||
            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
					            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
				
			||||||
| 
						 | 
					@ -54,9 +54,9 @@ pub trait ResourceScheme<T: Resource> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Resource operations */
 | 
					    /* Resource operations */
 | 
				
			||||||
    fn dup(&self, old_id: usize) -> Result<usize> {
 | 
					    fn dup(&self, old_id: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let old = unsafe { &*(old_id as *const T) };
 | 
					        let old = unsafe { &*(old_id as *const T) };
 | 
				
			||||||
        let resource = old.dup()?;
 | 
					        let resource = old.dup(buf)?;
 | 
				
			||||||
        let resource_ptr = Box::into_raw(resource);
 | 
					        let resource_ptr = Box::into_raw(resource);
 | 
				
			||||||
        Ok(resource_ptr as usize)
 | 
					        Ok(resource_ptr as usize)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,10 +52,14 @@ fn main() {
 | 
				
			||||||
                let mut event = Event::default();
 | 
					                let mut event = Event::default();
 | 
				
			||||||
                event_file.read(&mut event).expect("ahcid: failed to read event file");
 | 
					                event_file.read(&mut event).expect("ahcid: failed to read event file");
 | 
				
			||||||
                if event.id == socket_fd {
 | 
					                if event.id == socket_fd {
 | 
				
			||||||
                    let mut packet = Packet::default();
 | 
					                    loop {
 | 
				
			||||||
                    socket.read(&mut packet).expect("ahcid: failed to read disk scheme");
 | 
					                        let mut packet = Packet::default();
 | 
				
			||||||
                    scheme.handle(&mut packet);
 | 
					                        if socket.read(&mut packet).expect("ahcid: failed to read disk scheme") == 0 {
 | 
				
			||||||
                    socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
 | 
					                            break;
 | 
				
			||||||
 | 
					                        }                        
 | 
				
			||||||
 | 
					                        scheme.handle(&mut packet);
 | 
				
			||||||
 | 
					                        socket.write(&mut packet).expect("ahcid: failed to write disk scheme");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else if event.id == irq_fd {
 | 
					                } else if event.id == irq_fd {
 | 
				
			||||||
                    let mut irq = [0; 8];
 | 
					                    let mut irq = [0; 8];
 | 
				
			||||||
                    if irq_file.read(&mut irq).expect("ahcid: failed to read irq file") >= irq.len() {
 | 
					                    if irq_file.read(&mut irq).expect("ahcid: failed to read irq file") >= irq.len() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ impl Scheme for DiskScheme {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let mut handles = self.handles.lock();
 | 
					        let mut handles = self.handles.lock();
 | 
				
			||||||
        let new_handle = {
 | 
					        let new_handle = {
 | 
				
			||||||
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,7 +109,7 @@ impl Scheme for Intel8254x {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(id)
 | 
					        Ok(id)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,16 +80,20 @@ fn main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let socket_packet = socket.clone();
 | 
					            let socket_packet = socket.clone();
 | 
				
			||||||
            event_queue.add(socket_fd, move |_count: usize| -> Result<Option<usize>> {
 | 
					            event_queue.add(socket_fd, move |_count: usize| -> Result<Option<usize>> {
 | 
				
			||||||
                let mut packet = Packet::default();
 | 
					                loop {
 | 
				
			||||||
                socket_packet.borrow_mut().read(&mut packet)?;
 | 
					                    let mut packet = Packet::default();
 | 
				
			||||||
 | 
					                    if socket_packet.borrow_mut().read(&mut packet)? == 0 {
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let a = packet.a;
 | 
					                    let a = packet.a;
 | 
				
			||||||
                device.handle(&mut packet);
 | 
					                    device.handle(&mut packet);
 | 
				
			||||||
                if packet.a == (-EWOULDBLOCK) as usize {
 | 
					                    if packet.a == (-EWOULDBLOCK) as usize {
 | 
				
			||||||
                    packet.a = a;
 | 
					                        packet.a = a;
 | 
				
			||||||
                    todo.borrow_mut().push(packet);
 | 
					                        todo.borrow_mut().push(packet);
 | 
				
			||||||
                } else {
 | 
					                    } else {
 | 
				
			||||||
                    socket_packet.borrow_mut().write(&mut packet)?;
 | 
					                        socket_packet.borrow_mut().write(&mut packet)?;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let next_read = device.next_read();
 | 
					                let next_read = device.next_read();
 | 
				
			||||||
| 
						 | 
					@ -100,10 +104,8 @@ fn main() {
 | 
				
			||||||
                Ok(None)
 | 
					                Ok(None)
 | 
				
			||||||
            }).expect("e1000d: failed to catch events on IRQ file");
 | 
					            }).expect("e1000d: failed to catch events on IRQ file");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            loop {
 | 
					            for event_count in event_queue.trigger_all(0).expect("e1000d: failed to trigger events") {
 | 
				
			||||||
                let event_count = event_queue.run().expect("e1000d: failed to handle events");
 | 
					                socket.borrow_mut().write(&Packet {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                let event_packet = Packet {
 | 
					 | 
				
			||||||
                    id: 0,
 | 
					                    id: 0,
 | 
				
			||||||
                    pid: 0,
 | 
					                    pid: 0,
 | 
				
			||||||
                    uid: 0,
 | 
					                    uid: 0,
 | 
				
			||||||
| 
						 | 
					@ -112,9 +114,22 @@ fn main() {
 | 
				
			||||||
                    b: 0,
 | 
					                    b: 0,
 | 
				
			||||||
                    c: syscall::flag::EVENT_READ,
 | 
					                    c: syscall::flag::EVENT_READ,
 | 
				
			||||||
                    d: event_count
 | 
					                    d: event_count
 | 
				
			||||||
                };
 | 
					                }).expect("e1000d: failed to write event");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                socket.borrow_mut().write(&event_packet).expect("vesad: failed to write display event");
 | 
					            loop {
 | 
				
			||||||
 | 
					                let event_count = event_queue.run().expect("e1000d: failed to handle events");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                socket.borrow_mut().write(&Packet {
 | 
				
			||||||
 | 
					                    id: 0,
 | 
				
			||||||
 | 
					                    pid: 0,
 | 
				
			||||||
 | 
					                    uid: 0,
 | 
				
			||||||
 | 
					                    gid: 0,
 | 
				
			||||||
 | 
					                    a: syscall::number::SYS_FEVENT,
 | 
				
			||||||
 | 
					                    b: 0,
 | 
				
			||||||
 | 
					                    c: syscall::flag::EVENT_READ,
 | 
				
			||||||
 | 
					                    d: event_count
 | 
				
			||||||
 | 
					                }).expect("e1000d: failed to write event");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsafe { let _ = syscall::physunmap(address); }
 | 
					        unsafe { let _ = syscall::physunmap(address); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,92 @@ bitflags! {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Ps2d {
 | 
				
			||||||
 | 
					    input: File,
 | 
				
			||||||
 | 
					    lshift: bool,
 | 
				
			||||||
 | 
					    rshift: bool,
 | 
				
			||||||
 | 
					    packets: [u8; 4],
 | 
				
			||||||
 | 
					    packet_i: usize,
 | 
				
			||||||
 | 
					    extra_packet: bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Ps2d {
 | 
				
			||||||
 | 
					    fn new(input: File, extra_packet: bool) -> Self {
 | 
				
			||||||
 | 
					        Ps2d {
 | 
				
			||||||
 | 
					            input: input,
 | 
				
			||||||
 | 
					            lshift: false,
 | 
				
			||||||
 | 
					            rshift: false,
 | 
				
			||||||
 | 
					            packets: [0; 4],
 | 
				
			||||||
 | 
					            packet_i: 0,
 | 
				
			||||||
 | 
					            extra_packet: extra_packet
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn handle(&mut self, keyboard: bool, data: u8) {
 | 
				
			||||||
 | 
					        if keyboard {
 | 
				
			||||||
 | 
					            let (scancode, pressed) = if data >= 0x80 {
 | 
				
			||||||
 | 
					                (data - 0x80, false)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                (data, true)
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if scancode == 0x2A {
 | 
				
			||||||
 | 
					                self.lshift = pressed;
 | 
				
			||||||
 | 
					            } else if scancode == 0x36 {
 | 
				
			||||||
 | 
					                self.rshift = pressed;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.input.write(&KeyEvent {
 | 
				
			||||||
 | 
					                character: keymap::get_char(scancode, self.lshift || self.rshift),
 | 
				
			||||||
 | 
					                scancode: scancode,
 | 
				
			||||||
 | 
					                pressed: pressed
 | 
				
			||||||
 | 
					            }.to_event()).expect("ps2d: failed to write key event");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            self.packets[self.packet_i] = data;
 | 
				
			||||||
 | 
					            self.packet_i += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let flags = MousePacketFlags::from_bits_truncate(self.packets[0]);
 | 
				
			||||||
 | 
					            if ! flags.contains(ALWAYS_ON) {
 | 
				
			||||||
 | 
					                println!("MOUSE MISALIGN {:X}", self.packets[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.packets = [0; 4];
 | 
				
			||||||
 | 
					                self.packet_i = 0;
 | 
				
			||||||
 | 
					            } else if self.packet_i >= self.packets.len() || (!self.extra_packet && self.packet_i >= 3) {
 | 
				
			||||||
 | 
					                if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) {
 | 
				
			||||||
 | 
					                    let mut dx = self.packets[1] as i32;
 | 
				
			||||||
 | 
					                    if flags.contains(X_SIGN) {
 | 
				
			||||||
 | 
					                        dx -= 0x100;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let mut dy = -(self.packets[2] as i32);
 | 
				
			||||||
 | 
					                    if flags.contains(Y_SIGN) {
 | 
				
			||||||
 | 
					                        dy += 0x100;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let _extra = if self.extra_packet {
 | 
				
			||||||
 | 
					                        self.packets[3]
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        0
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    self.input.write(&MouseEvent {
 | 
				
			||||||
 | 
					                        x: dx,
 | 
				
			||||||
 | 
					                        y: dy,
 | 
				
			||||||
 | 
					                        left_button: flags.contains(LEFT_BUTTON),
 | 
				
			||||||
 | 
					                        middle_button: flags.contains(MIDDLE_BUTTON),
 | 
				
			||||||
 | 
					                        right_button: flags.contains(RIGHT_BUTTON)
 | 
				
			||||||
 | 
					                    }.to_event()).expect("ps2d: failed to write mouse event");
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    println!("ps2d: overflow {:X} {:X} {:X} {:X}", self.packets[0], self.packets[1], self.packets[2], self.packets[3]);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.packets = [0; 4];
 | 
				
			||||||
 | 
					                self.packet_i = 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    thread::spawn(|| {
 | 
					    thread::spawn(|| {
 | 
				
			||||||
        unsafe {
 | 
					        unsafe {
 | 
				
			||||||
| 
						 | 
					@ -39,9 +125,11 @@ fn main() {
 | 
				
			||||||
            asm!("cli" :::: "intel", "volatile");
 | 
					            asm!("cli" :::: "intel", "volatile");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let input = File::open("display:input").expect("ps2d: failed to open display:input");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let extra_packet = controller::Ps2::new().init();
 | 
					        let extra_packet = controller::Ps2::new().init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut input = File::open("display:input").expect("ps2d: failed to open display:input");
 | 
					        let mut ps2d = Ps2d::new(input, extra_packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut event_queue = EventQueue::<(bool, u8)>::new().expect("ps2d: failed to create event queue");
 | 
					        let mut event_queue = EventQueue::<(bool, u8)>::new().expect("ps2d: failed to create event queue");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,75 +169,13 @@ fn main() {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }).expect("ps2d: failed to poll irq:12");
 | 
					        }).expect("ps2d: failed to poll irq:12");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut lshift = false;
 | 
					        for (keyboard, data) in event_queue.trigger_all(0).expect("ps2d: failed to trigger events") {
 | 
				
			||||||
        let mut rshift = false;
 | 
					            ps2d.handle(keyboard, data);
 | 
				
			||||||
        let mut packets = [0; 4];
 | 
					        }
 | 
				
			||||||
        let mut packet_i = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            let (keyboard, data) = event_queue.run().expect("ps2d: failed to handle events");
 | 
					            let (keyboard, data) = event_queue.run().expect("ps2d: failed to handle events");
 | 
				
			||||||
 | 
					            ps2d.handle(keyboard, data);
 | 
				
			||||||
            if keyboard {
 | 
					 | 
				
			||||||
                let (scancode, pressed) = if data >= 0x80 {
 | 
					 | 
				
			||||||
                    (data - 0x80, false)
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    (data, true)
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if scancode == 0x2A {
 | 
					 | 
				
			||||||
                    lshift = pressed;
 | 
					 | 
				
			||||||
                } else if scancode == 0x36 {
 | 
					 | 
				
			||||||
                    rshift = pressed;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                input.write(&KeyEvent {
 | 
					 | 
				
			||||||
                    character: keymap::get_char(scancode, lshift || rshift),
 | 
					 | 
				
			||||||
                    scancode: scancode,
 | 
					 | 
				
			||||||
                    pressed: pressed
 | 
					 | 
				
			||||||
                }.to_event()).expect("ps2d: failed to write key event");
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                packets[packet_i] = data;
 | 
					 | 
				
			||||||
                packet_i += 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let flags = MousePacketFlags::from_bits_truncate(packets[0]);
 | 
					 | 
				
			||||||
                if ! flags.contains(ALWAYS_ON) {
 | 
					 | 
				
			||||||
                    println!("MOUSE MISALIGN {:X}", packets[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    packets = [0; 4];
 | 
					 | 
				
			||||||
                    packet_i = 0;
 | 
					 | 
				
			||||||
                } else if packet_i >= packets.len() || (!extra_packet && packet_i >= 3) {
 | 
					 | 
				
			||||||
                    if ! flags.contains(X_OVERFLOW) && ! flags.contains(Y_OVERFLOW) {
 | 
					 | 
				
			||||||
                        let mut dx = packets[1] as i32;
 | 
					 | 
				
			||||||
                        if flags.contains(X_SIGN) {
 | 
					 | 
				
			||||||
                            dx -= 0x100;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let mut dy = -(packets[2] as i32);
 | 
					 | 
				
			||||||
                        if flags.contains(Y_SIGN) {
 | 
					 | 
				
			||||||
                            dy += 0x100;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let _extra = if extra_packet {
 | 
					 | 
				
			||||||
                            packets[3]
 | 
					 | 
				
			||||||
                        } else {
 | 
					 | 
				
			||||||
                            0
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        input.write(&MouseEvent {
 | 
					 | 
				
			||||||
                            x: dx,
 | 
					 | 
				
			||||||
                            y: dy,
 | 
					 | 
				
			||||||
                            left_button: flags.contains(LEFT_BUTTON),
 | 
					 | 
				
			||||||
                            middle_button: flags.contains(MIDDLE_BUTTON),
 | 
					 | 
				
			||||||
                            right_button: flags.contains(RIGHT_BUTTON)
 | 
					 | 
				
			||||||
                        }.to_event()).expect("ps2d: failed to write mouse event");
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        println!("ps2d: overflow {:X} {:X} {:X} {:X}", packets[0], packets[1], packets[2], packets[3]);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    packets = [0; 4];
 | 
					 | 
				
			||||||
                    packet_i = 0;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ impl SchemeMut for Rtl8168 {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&mut self, id: usize) -> Result<usize> {
 | 
					    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(id)
 | 
					        Ok(id)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,16 +85,20 @@ fn main() {
 | 
				
			||||||
            let socket_fd = socket.borrow().as_raw_fd();
 | 
					            let socket_fd = socket.borrow().as_raw_fd();
 | 
				
			||||||
            let socket_packet = socket.clone();
 | 
					            let socket_packet = socket.clone();
 | 
				
			||||||
            event_queue.add(socket_fd, move |_count: usize| -> Result<Option<usize>> {
 | 
					            event_queue.add(socket_fd, move |_count: usize| -> Result<Option<usize>> {
 | 
				
			||||||
                let mut packet = Packet::default();
 | 
					                loop {
 | 
				
			||||||
                socket_packet.borrow_mut().read(&mut packet)?;
 | 
					                    let mut packet = Packet::default();
 | 
				
			||||||
 | 
					                    if socket_packet.borrow_mut().read(&mut packet)? == 0 {
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let a = packet.a;
 | 
					                    let a = packet.a;
 | 
				
			||||||
                device.borrow_mut().handle(&mut packet);
 | 
					                    device.borrow_mut().handle(&mut packet);
 | 
				
			||||||
                if packet.a == (-EWOULDBLOCK) as usize {
 | 
					                    if packet.a == (-EWOULDBLOCK) as usize {
 | 
				
			||||||
                    packet.a = a;
 | 
					                        packet.a = a;
 | 
				
			||||||
                    todo.borrow_mut().push(packet);
 | 
					                        todo.borrow_mut().push(packet);
 | 
				
			||||||
                } else {
 | 
					                    } else {
 | 
				
			||||||
                    socket_packet.borrow_mut().write(&mut packet)?;
 | 
					                        socket_packet.borrow_mut().write(&mut packet)?;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let next_read = device.borrow().next_read();
 | 
					                let next_read = device.borrow().next_read();
 | 
				
			||||||
| 
						 | 
					@ -105,10 +109,8 @@ fn main() {
 | 
				
			||||||
                Ok(None)
 | 
					                Ok(None)
 | 
				
			||||||
            }).expect("rtl8168d: failed to catch events on IRQ file");
 | 
					            }).expect("rtl8168d: failed to catch events on IRQ file");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            loop {
 | 
					            for event_count in event_queue.trigger_all(0).expect("rtl8168d: failed to trigger events") {
 | 
				
			||||||
                let event_count = event_queue.run().expect("rtl8168d: failed to handle events");
 | 
					                socket.borrow_mut().write(&Packet {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                let event_packet = Packet {
 | 
					 | 
				
			||||||
                    id: 0,
 | 
					                    id: 0,
 | 
				
			||||||
                    pid: 0,
 | 
					                    pid: 0,
 | 
				
			||||||
                    uid: 0,
 | 
					                    uid: 0,
 | 
				
			||||||
| 
						 | 
					@ -117,9 +119,22 @@ fn main() {
 | 
				
			||||||
                    b: 0,
 | 
					                    b: 0,
 | 
				
			||||||
                    c: syscall::flag::EVENT_READ,
 | 
					                    c: syscall::flag::EVENT_READ,
 | 
				
			||||||
                    d: event_count
 | 
					                    d: event_count
 | 
				
			||||||
                };
 | 
					                }).expect("rtl8168d: failed to write event");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                socket.borrow_mut().write(&event_packet).expect("vesad: failed to write display event");
 | 
					            loop {
 | 
				
			||||||
 | 
					                let event_count = event_queue.run().expect("rtl8168d: failed to handle events");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                socket.borrow_mut().write(&Packet {
 | 
				
			||||||
 | 
					                    id: 0,
 | 
				
			||||||
 | 
					                    pid: 0,
 | 
				
			||||||
 | 
					                    uid: 0,
 | 
				
			||||||
 | 
					                    gid: 0,
 | 
				
			||||||
 | 
					                    a: syscall::number::SYS_FEVENT,
 | 
				
			||||||
 | 
					                    b: 0,
 | 
				
			||||||
 | 
					                    c: syscall::flag::EVENT_READ,
 | 
				
			||||||
 | 
					                    d: event_count
 | 
				
			||||||
 | 
					                }).expect("rtl8168d: failed to write event");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        unsafe { let _ = syscall::physunmap(address); }
 | 
					        unsafe { let _ = syscall::physunmap(address); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,6 @@ fn main() {
 | 
				
			||||||
            loop {
 | 
					            loop {
 | 
				
			||||||
                let mut packet = Packet::default();
 | 
					                let mut packet = Packet::default();
 | 
				
			||||||
                socket.read(&mut packet).expect("vesad: failed to read display scheme");
 | 
					                socket.read(&mut packet).expect("vesad: failed to read display scheme");
 | 
				
			||||||
                //println!("vesad: {:?}", packet);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // If it is a read packet, and there is no data, block it. Otherwise, handle packet
 | 
					                // If it is a read packet, and there is no data, block it. Otherwise, handle packet
 | 
				
			||||||
                if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.will_block(packet.b) {
 | 
					                if packet.a == syscall::number::SYS_READ && packet.d > 0 && scheme.will_block(packet.b) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ impl SchemeMut for DisplayScheme {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&mut self, id: usize) -> Result<usize> {
 | 
					    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(id)
 | 
					        Ok(id)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,6 @@
 | 
				
			||||||
randd
 | 
					randd
 | 
				
			||||||
initfs:bin/pcid /etc/pcid.toml
 | 
					initfs:bin/pcid /etc/pcid.toml
 | 
				
			||||||
ethernetd
 | 
					ethernetd
 | 
				
			||||||
arpd
 | 
					 | 
				
			||||||
ipd
 | 
					ipd
 | 
				
			||||||
tcpd
 | 
					tcpd
 | 
				
			||||||
udpd
 | 
					udpd
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ impl Scheme for DebugScheme {
 | 
				
			||||||
        Ok(0)
 | 
					        Ok(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, _file: usize) -> Result<usize> {
 | 
					    fn dup(&self, _file: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(0)
 | 
					        Ok(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ impl Scheme for EnvScheme {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let new_handle = {
 | 
					        let new_handle = {
 | 
				
			||||||
            let handles = self.handles.read();
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ impl Scheme for EventScheme {
 | 
				
			||||||
        Ok(id)
 | 
					        Ok(id)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let handle = {
 | 
					        let handle = {
 | 
				
			||||||
            let handles = self.handles.read();
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
            let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					            let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@ impl Scheme for InitFsScheme {
 | 
				
			||||||
        Err(Error::new(ENOENT))
 | 
					        Err(Error::new(ENOENT))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let (path, data, mode, seek) = {
 | 
					        let (path, data, mode, seek) = {
 | 
				
			||||||
            let handles = self.handles.read();
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ impl Scheme for IrqScheme {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, file: usize) -> Result<usize> {
 | 
					    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(file)
 | 
					        Ok(file)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ pub fn pipe(flags: usize) -> (usize, usize) {
 | 
				
			||||||
pub struct PipeScheme;
 | 
					pub struct PipeScheme;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Scheme for PipeScheme {
 | 
					impl Scheme for PipeScheme {
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let mut pipes = pipes_mut();
 | 
					        let mut pipes = pipes_mut();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
 | 
					        let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ impl Scheme for RootScheme {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, file: usize) -> Result<usize> {
 | 
					    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let mut handles = self.handles.write();
 | 
					        let mut handles = self.handles.write();
 | 
				
			||||||
        let inner = {
 | 
					        let inner = {
 | 
				
			||||||
            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
					            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					@ -89,12 +89,24 @@ impl Scheme for RootScheme {
 | 
				
			||||||
        inner.write(buf)
 | 
					        inner.write(buf)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn fevent(&self, file: usize, _flags: usize) -> Result<usize> {
 | 
					    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
 | 
				
			||||||
        Ok(file)
 | 
					        let inner = {
 | 
				
			||||||
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
 | 
					            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					            inner.clone()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inner.fevent(flags)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn fsync(&self, _file: usize) -> Result<usize> {
 | 
					    fn fsync(&self, file: usize) -> Result<usize> {
 | 
				
			||||||
        Ok(0)
 | 
					        let inner = {
 | 
				
			||||||
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
 | 
					            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					            inner.clone()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inner.fsync()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn close(&self, file: usize) -> Result<usize> {
 | 
					    fn close(&self, file: usize) -> Result<usize> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,7 +92,7 @@ impl Scheme for SysScheme {
 | 
				
			||||||
        Err(Error::new(ENOENT))
 | 
					        Err(Error::new(ENOENT))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, id: usize) -> Result<usize> {
 | 
					    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let (path, data, mode, seek) = {
 | 
					        let (path, data, mode, seek) = {
 | 
				
			||||||
            let handles = self.handles.read();
 | 
					            let handles = self.handles.read();
 | 
				
			||||||
            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					            let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,10 +61,7 @@ impl UserInner {
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let len = self.todo.send(packet);
 | 
					        let len = self.todo.send(packet);
 | 
				
			||||||
        //TODO: Use O_NONBLOCK and send one notification
 | 
					        context::event::trigger(ROOT_SCHEME_ID.load(Ordering::SeqCst), self.handle_id, EVENT_READ, mem::size_of::<Packet>() * len);
 | 
				
			||||||
        for _i in 0 .. len {
 | 
					 | 
				
			||||||
            context::event::trigger(ROOT_SCHEME_ID.load(Ordering::SeqCst), self.handle_id, EVENT_READ, mem::size_of::<Packet>());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Error::demux(self.done.receive(&id))
 | 
					        Error::demux(self.done.receive(&id))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -182,6 +179,14 @@ impl UserInner {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(i * packet_size)
 | 
					        Ok(i * packet_size)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn fevent(&self, _flags: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        Ok(self.handle_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn fsync(&self) -> Result<usize> {
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// UserInner has to be wrapped
 | 
					/// UserInner has to be wrapped
 | 
				
			||||||
| 
						 | 
					@ -230,9 +235,12 @@ impl Scheme for UserScheme {
 | 
				
			||||||
        result
 | 
					        result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, file: usize) -> Result<usize> {
 | 
					    fn dup(&self, file: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
 | 
					        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
        inner.call(SYS_DUP, file, 0, 0)
 | 
					        let address = inner.capture(buf)?;
 | 
				
			||||||
 | 
					        let result = inner.call(SYS_DUP, file, address, buf.len());
 | 
				
			||||||
 | 
					        let _ = inner.release(address);
 | 
				
			||||||
 | 
					        result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
 | 
					    fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,10 +83,10 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
 | 
				
			||||||
    let reference_opt = parts.next();
 | 
					    let reference_opt = parts.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let (scheme_id, file_id) = {
 | 
					    let (scheme_id, file_id) = {
 | 
				
			||||||
        let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
 | 
					        let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
        let (scheme_id, scheme) = {
 | 
					        let (scheme_id, scheme) = {
 | 
				
			||||||
            let schemes = scheme::schemes();
 | 
					            let schemes = scheme::schemes();
 | 
				
			||||||
            let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
 | 
					            let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
            (scheme_id, scheme.clone())
 | 
					            (scheme_id, scheme.clone())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?;
 | 
					        let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?;
 | 
				
			||||||
| 
						 | 
					@ -146,10 +146,10 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
 | 
				
			||||||
    let namespace_opt = parts.next();
 | 
					    let namespace_opt = parts.next();
 | 
				
			||||||
    let reference_opt = parts.next();
 | 
					    let reference_opt = parts.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
 | 
					    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
    let scheme = {
 | 
					    let scheme = {
 | 
				
			||||||
        let schemes = scheme::schemes();
 | 
					        let schemes = scheme::schemes();
 | 
				
			||||||
        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
 | 
					        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
        scheme.clone()
 | 
					        scheme.clone()
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid)
 | 
					    scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid)
 | 
				
			||||||
| 
						 | 
					@ -168,10 +168,10 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
 | 
				
			||||||
    let namespace_opt = parts.next();
 | 
					    let namespace_opt = parts.next();
 | 
				
			||||||
    let reference_opt = parts.next();
 | 
					    let reference_opt = parts.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
 | 
					    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
    let scheme = {
 | 
					    let scheme = {
 | 
				
			||||||
        let schemes = scheme::schemes();
 | 
					        let schemes = scheme::schemes();
 | 
				
			||||||
        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
 | 
					        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
        scheme.clone()
 | 
					        scheme.clone()
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
 | 
					    scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
 | 
				
			||||||
| 
						 | 
					@ -190,10 +190,10 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
 | 
				
			||||||
    let namespace_opt = parts.next();
 | 
					    let namespace_opt = parts.next();
 | 
				
			||||||
    let reference_opt = parts.next();
 | 
					    let reference_opt = parts.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
 | 
					    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
    let scheme = {
 | 
					    let scheme = {
 | 
				
			||||||
        let schemes = scheme::schemes();
 | 
					        let schemes = scheme::schemes();
 | 
				
			||||||
        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
 | 
					        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
 | 
				
			||||||
        scheme.clone()
 | 
					        scheme.clone()
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
 | 
					    scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
 | 
				
			||||||
| 
						 | 
					@ -222,7 +222,7 @@ pub fn close(fd: usize) -> Result<usize> {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Duplicate file descriptor
 | 
					/// Duplicate file descriptor
 | 
				
			||||||
pub fn dup(fd: usize) -> Result<usize> {
 | 
					pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
    let file = {
 | 
					    let file = {
 | 
				
			||||||
        let contexts = context::contexts();
 | 
					        let contexts = context::contexts();
 | 
				
			||||||
        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
 | 
					        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
 | 
				
			||||||
| 
						 | 
					@ -237,7 +237,7 @@ pub fn dup(fd: usize) -> Result<usize> {
 | 
				
			||||||
            let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
 | 
					            let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
            scheme.clone()
 | 
					            scheme.clone()
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        scheme.dup(file.number)?
 | 
					        scheme.dup(file.number, buf)?
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let contexts = context::contexts();
 | 
					    let contexts = context::contexts();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
 | 
				
			||||||
                SYS_ARG_MSLICE => file_op_mut_slice(a, b, validate_slice_mut(c as *mut u8, d)?),
 | 
					                SYS_ARG_MSLICE => file_op_mut_slice(a, b, validate_slice_mut(c as *mut u8, d)?),
 | 
				
			||||||
                _ => match a {
 | 
					                _ => match a {
 | 
				
			||||||
                    SYS_CLOSE => close(b),
 | 
					                    SYS_CLOSE => close(b),
 | 
				
			||||||
                    SYS_DUP => dup(b),
 | 
					                    SYS_DUP => dup(b, validate_slice(c as *const u8, d)?),
 | 
				
			||||||
                    SYS_FEVENT => fevent(b, c),
 | 
					                    SYS_FEVENT => fevent(b, c),
 | 
				
			||||||
                    _ => file_op(a, b, c, d)
 | 
					                    _ => file_op(a, b, c, d)
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,7 +227,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
 | 
				
			||||||
                            let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
 | 
					                            let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
                            scheme.clone()
 | 
					                            scheme.clone()
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
                        let result = scheme.dup(file.number);
 | 
					                        let result = scheme.dup(file.number, &[]);
 | 
				
			||||||
                        result
 | 
					                        result
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    match result {
 | 
					                    match result {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								libstd
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								libstd
									
										
									
									
									
								
							| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 4f642eed87af22913af7bef9c71910ee1765445e
 | 
					Subproject commit a390903a03d7cebe448af803e635a46fa1609262
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 9faaf3a9690186a12da980fb877c8f05faea62aa
 | 
					Subproject commit 1afcf7ab26ca3f697082674e6a72c94dd211c74b
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 4eae543a60a5d6b0298db09bc48b2e6fab60b021
 | 
					Subproject commit 6926b235c47488f1bb2f5574a0445c7698e3ab99
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 517ca6d125e90d6b30e45a759f54b1d1b3b346d4
 | 
					Subproject commit 78cd23bf67adad79fb3e45ae4647055b01df026f
 | 
				
			||||||
| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
[package]
 | 
					 | 
				
			||||||
name = "arpd"
 | 
					 | 
				
			||||||
version = "0.1.0"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[dependencies]
 | 
					 | 
				
			||||||
netutils = { path = "../../programs/netutils/" }
 | 
					 | 
				
			||||||
syscall = { path = "../../syscall/" }
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,40 +0,0 @@
 | 
				
			||||||
extern crate netutils;
 | 
					 | 
				
			||||||
extern crate syscall;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{getcfg, Ipv4Addr, MacAddr, Arp};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use std::thread;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn main() {
 | 
					 | 
				
			||||||
    thread::spawn(move || {
 | 
					 | 
				
			||||||
        while let Ok(link) = syscall::open("ethernet:/806", syscall::O_RDWR) {
 | 
					 | 
				
			||||||
            loop {
 | 
					 | 
				
			||||||
                let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                if let Ok(count) = syscall::read(link, &mut bytes) {
 | 
					 | 
				
			||||||
                    if let Some(packet) = Arp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                        let mac_addr = MacAddr::from_str(&getcfg("mac").expect("arpd: failed to get mac address"));
 | 
					 | 
				
			||||||
                        let ip_addr = Ipv4Addr::from_str(&getcfg("ip").expect("arpd: failed to get ip address"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if packet.header.oper.get() == 1 && packet.header.dst_ip.equals(ip_addr) {
 | 
					 | 
				
			||||||
                            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 = mac_addr;
 | 
					 | 
				
			||||||
                            response.header.src_ip = ip_addr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let _ = syscall::write(link, &response.to_bytes());
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let _ = syscall::close(link);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        panic!("ARP: Failed to open ethernet");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -68,21 +68,27 @@ fn main() {
 | 
				
			||||||
        }).expect("ethernetd: failed to listen for network events");
 | 
					        }).expect("ethernetd: failed to listen for network events");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        event_queue.add(socket_fd, move |_count: usize| -> Result<Option<()>> {
 | 
					        event_queue.add(socket_fd, move |_count: usize| -> Result<Option<()>> {
 | 
				
			||||||
            let mut packet = Packet::default();
 | 
					            loop {
 | 
				
			||||||
            socket.borrow_mut().read(&mut packet)?;
 | 
					                let mut packet = Packet::default();
 | 
				
			||||||
 | 
					                if socket.borrow_mut().read(&mut packet)? == 0 {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let a = packet.a;
 | 
					                let a = packet.a;
 | 
				
			||||||
            scheme.borrow_mut().handle(&mut packet);
 | 
					                scheme.borrow_mut().handle(&mut packet);
 | 
				
			||||||
            if packet.a == (-EWOULDBLOCK) as usize {
 | 
					                if packet.a == (-EWOULDBLOCK) as usize {
 | 
				
			||||||
                packet.a = a;
 | 
					                    packet.a = a;
 | 
				
			||||||
                todo.borrow_mut().push(packet);
 | 
					                    todo.borrow_mut().push(packet);
 | 
				
			||||||
            } else {
 | 
					                } else {
 | 
				
			||||||
                socket.borrow_mut().write(&mut packet)?;
 | 
					                    socket.borrow_mut().write(&mut packet)?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Ok(None)
 | 
					            Ok(None)
 | 
				
			||||||
        }).expect("ethernetd: failed to listen for scheme events");
 | 
					        }).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");
 | 
					        event_queue.run().expect("ethernetd: failed to run event loop");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +1,21 @@
 | 
				
			||||||
use std::collections::{BTreeMap, VecDeque};
 | 
					use std::collections::{BTreeMap, VecDeque};
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::{self, Read};
 | 
					use std::io::{self, Read, Write};
 | 
				
			||||||
use std::os::unix::io::AsRawFd;
 | 
					use std::os::unix::io::AsRawFd;
 | 
				
			||||||
use std::{cmp, str, u16};
 | 
					use std::{cmp, str, u16};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use netutils::{getcfg, n16, MacAddr, EthernetII, EthernetIIHeader};
 | 
					use netutils::{getcfg, MacAddr, EthernetII};
 | 
				
			||||||
use syscall;
 | 
					use syscall;
 | 
				
			||||||
use syscall::error::{Error, Result, EACCES, EBADF, ENOENT, EINVAL, EWOULDBLOCK};
 | 
					use syscall::error::{Error, Result, EACCES, EBADF, EINVAL, EWOULDBLOCK};
 | 
				
			||||||
 | 
					use syscall::flag::O_NONBLOCK;
 | 
				
			||||||
use syscall::scheme::SchemeMut;
 | 
					use syscall::scheme::SchemeMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub struct Handle {
 | 
					pub struct Handle {
 | 
				
			||||||
 | 
					    /// The flags this handle was opened with
 | 
				
			||||||
 | 
					    flags: usize,
 | 
				
			||||||
    /// The Host's MAC address
 | 
					    /// The Host's MAC address
 | 
				
			||||||
    pub host_addr: MacAddr,
 | 
					    pub host_addr: MacAddr,
 | 
				
			||||||
    /// The Peer's MAC address
 | 
					 | 
				
			||||||
    pub peer_addr: Option<MacAddr>,
 | 
					 | 
				
			||||||
    /// The ethernet type
 | 
					    /// The ethernet type
 | 
				
			||||||
    pub ethertype: u16,
 | 
					    pub ethertype: u16,
 | 
				
			||||||
    /// The data
 | 
					    /// The data
 | 
				
			||||||
| 
						 | 
					@ -39,65 +40,51 @@ impl EthernetScheme {
 | 
				
			||||||
    //TODO: Minimize allocation
 | 
					    //TODO: Minimize allocation
 | 
				
			||||||
    //TODO: Reduce iteration cost (use BTreeMap of ethertype to handle?)
 | 
					    //TODO: Reduce iteration cost (use BTreeMap of ethertype to handle?)
 | 
				
			||||||
    pub fn input(&mut self) -> io::Result<usize> {
 | 
					    pub fn input(&mut self) -> io::Result<usize> {
 | 
				
			||||||
        let mut bytes = [0; 65536];
 | 
					        let mut total = 0;
 | 
				
			||||||
        let count = self.network.read(&mut bytes)?;
 | 
					        loop {
 | 
				
			||||||
        if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) {
 | 
					            let mut bytes = [0; 65536];
 | 
				
			||||||
            for (_id, handle) in self.handles.iter_mut() {
 | 
					            let count = self.network.read(&mut bytes)?;
 | 
				
			||||||
                if frame.header.ethertype.get() == handle.ethertype {
 | 
					            if count == 0 {
 | 
				
			||||||
                    if handle.peer_addr.is_none() {
 | 
					                break;
 | 
				
			||||||
                        handle.peer_addr = Some(frame.header.src);
 | 
					            }
 | 
				
			||||||
                    }
 | 
					            if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) {
 | 
				
			||||||
                    handle.frames.push_back(frame.clone());
 | 
					                for (_id, handle) in self.handles.iter_mut() {
 | 
				
			||||||
                }
 | 
					                    if frame.header.ethertype.get() == handle.ethertype {
 | 
				
			||||||
 | 
					                        handle.frames.push_back(frame.clone());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                total += count;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Ok(count)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ok(0)
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(total)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl SchemeMut for EthernetScheme {
 | 
					impl SchemeMut for EthernetScheme {
 | 
				
			||||||
    fn open(&mut self, url: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<usize> {
 | 
					    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
 | 
				
			||||||
        if uid == 0 {
 | 
					        if uid == 0 {
 | 
				
			||||||
            let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| err.into_sys())?);
 | 
					            let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| err.into_sys())?);
 | 
				
			||||||
            let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
 | 
					            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() {
 | 
					 | 
				
			||||||
                    let ethertype = u16::from_str_radix(ethertype_string, 16).unwrap_or(0);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let peer_addr = if ! host_string.is_empty() {
 | 
					            let ethertype = u16::from_str_radix(path, 16).unwrap_or(0);
 | 
				
			||||||
                        Some(MacAddr::from_str(host_string))
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        None
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let next_id = self.next_id;
 | 
					            let next_id = self.next_id;
 | 
				
			||||||
                    self.next_id += 1;
 | 
					            self.next_id += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    self.handles.insert(next_id, Handle {
 | 
					            self.handles.insert(next_id, Handle {
 | 
				
			||||||
                        host_addr: mac_addr,
 | 
					                flags: flags,
 | 
				
			||||||
                        peer_addr: peer_addr,
 | 
					                host_addr: mac_addr,
 | 
				
			||||||
                        ethertype: ethertype,
 | 
					                ethertype: ethertype,
 | 
				
			||||||
                        frames: VecDeque::new()
 | 
					                frames: VecDeque::new()
 | 
				
			||||||
                    });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return Ok(next_id);
 | 
					            Ok(next_id)
 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    println!("Ethernet: No ethertype provided");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                println!("Ethernet: No host provided");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Err(Error::new(ENOENT))
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(Error::new(EACCES))
 | 
					            Err(Error::new(EACCES))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&mut self, id: usize) -> Result<usize> {
 | 
					    fn dup(&mut self, id: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let next_id = self.next_id;
 | 
					        let next_id = self.next_id;
 | 
				
			||||||
        self.next_id += 1;
 | 
					        self.next_id += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,11 +102,14 @@ impl SchemeMut for EthernetScheme {
 | 
				
			||||||
        let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
 | 
					        let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Some(frame) = handle.frames.pop_front() {
 | 
					        if let Some(frame) = handle.frames.pop_front() {
 | 
				
			||||||
            for (b, d) in buf.iter_mut().zip(frame.data.iter()) {
 | 
					            let data = frame.to_bytes();
 | 
				
			||||||
 | 
					            for (b, d) in buf.iter_mut().zip(data.iter()) {
 | 
				
			||||||
                *b = *d;
 | 
					                *b = *d;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Ok(cmp::min(buf.len(), frame.data.len()))
 | 
					            Ok(cmp::min(buf.len(), data.len()))
 | 
				
			||||||
 | 
					        } else if handle.flags & O_NONBLOCK == O_NONBLOCK {
 | 
				
			||||||
 | 
					            Ok(0)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(Error::new(EWOULDBLOCK))
 | 
					            Err(Error::new(EWOULDBLOCK))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -128,17 +118,12 @@ impl SchemeMut for EthernetScheme {
 | 
				
			||||||
    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
 | 
					    fn write(&mut self, id: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match syscall::write(self.network.as_raw_fd(), &EthernetII {
 | 
					        if let Some(mut frame) = EthernetII::from_bytes(buf) {
 | 
				
			||||||
                                      header: EthernetIIHeader {
 | 
					            frame.header.src = handle.host_addr;
 | 
				
			||||||
                                          src: handle.host_addr,
 | 
					            frame.header.ethertype.set(handle.ethertype);
 | 
				
			||||||
                                          dst: handle.peer_addr.unwrap_or(MacAddr::BROADCAST),
 | 
					            self.network.write(&frame.to_bytes()).map_err(|err| err.into_sys())
 | 
				
			||||||
                                          ethertype: n16::new(handle.ethertype),
 | 
					        } else {
 | 
				
			||||||
                                      },
 | 
					            Err(Error::new(EINVAL))
 | 
				
			||||||
                                      data: Vec::from(buf),
 | 
					 | 
				
			||||||
                                  }
 | 
					 | 
				
			||||||
                                  .to_bytes()) {
 | 
					 | 
				
			||||||
            Ok(_) => Ok(buf.len()),
 | 
					 | 
				
			||||||
            Err(err) => Err(err),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,14 +136,16 @@ impl SchemeMut for EthernetScheme {
 | 
				
			||||||
    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
 | 
					    fn fpath(&mut self, id: usize, buf: &mut [u8]) -> Result<usize> {
 | 
				
			||||||
        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
					        let handle = self.handles.get(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let path_string = format!("ethernet:{}/{:X}", handle.peer_addr.map_or(String::new(), |mac| mac.to_string()), handle.ethertype);
 | 
					        let path_string = format!("ethernet:{:X}", handle.ethertype);
 | 
				
			||||||
        let path = path_string.as_bytes();
 | 
					        let path = path_string.as_bytes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (b, p) in buf.iter_mut().zip(path.iter()) {
 | 
					        let mut i = 0;
 | 
				
			||||||
            *b = *p;
 | 
					        while i < buf.len() && i < path.len() {
 | 
				
			||||||
 | 
					            buf[i] = path[i];
 | 
				
			||||||
 | 
					            i += 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(cmp::min(buf.len(), path.len()))
 | 
					        Ok(i)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn fsync(&mut self, id: usize) -> Result<usize> {
 | 
					    fn fsync(&mut self, id: usize) -> Result<usize> {
 | 
				
			||||||
| 
						 | 
					@ -169,7 +156,9 @@ impl SchemeMut for EthernetScheme {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn close(&mut self, id: usize) -> Result<usize> {
 | 
					    fn close(&mut self, id: usize) -> Result<usize> {
 | 
				
			||||||
        let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?;
 | 
					        let handle = self.handles.remove(&id).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        drop(handle);
 | 
					        drop(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(0)
 | 
					        Ok(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,7 +15,7 @@ impl Scheme for ExampleScheme {
 | 
				
			||||||
        Ok(0)
 | 
					        Ok(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, file: usize) -> Result<usize> {
 | 
					    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(file)
 | 
					        Ok(file)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,6 @@ name = "ipd"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					event = { path = "../../crates/event/" }
 | 
				
			||||||
netutils = { path = "../../programs/netutils/" }
 | 
					netutils = { path = "../../programs/netutils/" }
 | 
				
			||||||
resource_scheme = { path = "../../crates/resource_scheme/" }
 | 
					 | 
				
			||||||
syscall = { path = "../../syscall/" }
 | 
					syscall = { path = "../../syscall/" }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,120 +1,371 @@
 | 
				
			||||||
#![feature(rand)]
 | 
					extern crate event;
 | 
				
			||||||
 | 
					 | 
				
			||||||
//! Implementation of the IP Scheme as a userland driver.
 | 
					 | 
				
			||||||
//!
 | 
					 | 
				
			||||||
//! # Role
 | 
					 | 
				
			||||||
//!
 | 
					 | 
				
			||||||
//! See https://en.wikipedia.org/wiki/Internet_Protocol for more details about the
 | 
					 | 
				
			||||||
//! IP protocol. Clients will often prefer using either higher-level protocols TCP
 | 
					 | 
				
			||||||
//! or UDP, both of which are built upon IP.
 | 
					 | 
				
			||||||
//!
 | 
					 | 
				
			||||||
//! # URL Syntax
 | 
					 | 
				
			||||||
//!
 | 
					 | 
				
			||||||
//! To open a IP connection, use `ip:[host]/protocol`.
 | 
					 | 
				
			||||||
//!
 | 
					 | 
				
			||||||
//! * If `host` is specified, it must be an ipv4 number (e.g. `192.168.0.1`)
 | 
					 | 
				
			||||||
//! and the connection may be used immediately to send/receive data. Ip v4 number
 | 
					 | 
				
			||||||
//! `127.0.0.1` is hardwired to the loopback device (i.e. localhost), which doesn't
 | 
					 | 
				
			||||||
//! access any physical device and in which data can only be read by the same
 | 
					 | 
				
			||||||
//! connection that has written it.
 | 
					 | 
				
			||||||
//! * If `host` is omitted, this connectino will wait for a distant peer to
 | 
					 | 
				
			||||||
//! connect.
 | 
					 | 
				
			||||||
//! * The `protocol` is the hex-based number of the ip protocol
 | 
					 | 
				
			||||||
//! (see http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern crate netutils;
 | 
					extern crate netutils;
 | 
				
			||||||
extern crate resource_scheme;
 | 
					 | 
				
			||||||
extern crate syscall;
 | 
					extern crate syscall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use event::EventQueue;
 | 
				
			||||||
 | 
					use netutils::{getcfg, n16, Ipv4Addr, MacAddr, Ipv4, EthernetII, EthernetIIHeader, Arp, Tcp};
 | 
				
			||||||
 | 
					use std::cell::RefCell;
 | 
				
			||||||
 | 
					use std::collections::{BTreeMap, VecDeque};
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::{Read, Write};
 | 
					use std::io::{self, Read, Write};
 | 
				
			||||||
use std::thread;
 | 
					use std::os::unix::io::FromRawFd;
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					use std::{slice, str, thread};
 | 
				
			||||||
 | 
					use syscall::data::Packet;
 | 
				
			||||||
 | 
					use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EINVAL, ENOENT, EWOULDBLOCK};
 | 
				
			||||||
 | 
					use syscall::flag::{EVENT_READ, O_NONBLOCK};
 | 
				
			||||||
 | 
					use syscall::scheme::SchemeMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					struct Interface {
 | 
				
			||||||
use syscall::Packet;
 | 
					    mac: MacAddr,
 | 
				
			||||||
 | 
					    ip: Ipv4Addr,
 | 
				
			||||||
 | 
					    router: Ipv4Addr,
 | 
				
			||||||
 | 
					    subnet: Ipv4Addr,
 | 
				
			||||||
 | 
					    arp_file: File,
 | 
				
			||||||
 | 
					    ip_file: File,
 | 
				
			||||||
 | 
					    arp: BTreeMap<Ipv4Addr, MacAddr>,
 | 
				
			||||||
 | 
					    rarp: BTreeMap<MacAddr, Ipv4Addr>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use scheme::IpScheme;
 | 
					impl Interface {
 | 
				
			||||||
 | 
					    fn new(arp_fd: usize, ip_fd: usize) -> Self {
 | 
				
			||||||
 | 
					        Interface {
 | 
				
			||||||
 | 
					            mac: MacAddr::from_str(&getcfg("mac").unwrap()),
 | 
				
			||||||
 | 
					            ip: Ipv4Addr::from_str(&getcfg("ip").unwrap()),
 | 
				
			||||||
 | 
					            router: Ipv4Addr::from_str(&getcfg("ip_router").unwrap()),
 | 
				
			||||||
 | 
					            subnet: Ipv4Addr::from_str(&getcfg("ip_subnet").unwrap()),
 | 
				
			||||||
 | 
					            arp_file: unsafe { File::from_raw_fd(arp_fd) },
 | 
				
			||||||
 | 
					            ip_file: unsafe { File::from_raw_fd(ip_fd) },
 | 
				
			||||||
 | 
					            arp: BTreeMap::new(),
 | 
				
			||||||
 | 
					            rarp: BTreeMap::new(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod resource;
 | 
					struct Handle {
 | 
				
			||||||
mod scheme;
 | 
					    proto: u8,
 | 
				
			||||||
 | 
					    flags: usize,
 | 
				
			||||||
 | 
					    events: usize,
 | 
				
			||||||
 | 
					    data: VecDeque<Vec<u8>>,
 | 
				
			||||||
 | 
					    todo: VecDeque<Packet>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Ipd {
 | 
				
			||||||
 | 
					    scheme_file: File,
 | 
				
			||||||
 | 
					    interfaces: Vec<Interface>,
 | 
				
			||||||
 | 
					    next_id: usize,
 | 
				
			||||||
 | 
					    handles: BTreeMap<usize, Handle>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 arp_event(&mut self, if_id: usize) -> io::Result<()> {
 | 
				
			||||||
 | 
					        if let Some(mut interface) = self.interfaces.get_mut(if_id) {
 | 
				
			||||||
 | 
					            loop {
 | 
				
			||||||
 | 
					                let mut bytes = [0; 65536];
 | 
				
			||||||
 | 
					                let count = interface.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 == interface.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 = interface.mac;
 | 
				
			||||||
 | 
					                                response.header.src_ip = interface.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 = interface.mac;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                interface.arp_file.write(&response_frame.to_bytes())?;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn ip_event(&mut self, if_id: usize) -> io::Result<()> {
 | 
				
			||||||
 | 
					        if let Some(mut interface) = self.interfaces.get_mut(if_id) {
 | 
				
			||||||
 | 
					            loop {
 | 
				
			||||||
 | 
					                let mut bytes = [0; 65536];
 | 
				
			||||||
 | 
					                let count = interface.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 == interface.ip || ip.header.dst == Ipv4Addr::BROADCAST {
 | 
				
			||||||
 | 
					                            //TODO: Handle ping here
 | 
				
			||||||
 | 
					                            for (id, handle) in self.handles.iter_mut() {
 | 
				
			||||||
 | 
					                                if ip.header.proto == handle.proto {
 | 
				
			||||||
 | 
					                                    handle.data.push_back(frame.data.clone());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                    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(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl SchemeMut for Ipd {
 | 
				
			||||||
 | 
					    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        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() {
 | 
				
			||||||
 | 
					                if ip.header.src == interface.ip || ip.header.src == Ipv4Addr::NULL {
 | 
				
			||||||
 | 
					                    ip.header.src = interface.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();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    let frame = EthernetII {
 | 
				
			||||||
 | 
					                        header: EthernetIIHeader {
 | 
				
			||||||
 | 
					                            //TODO: Get real dst
 | 
				
			||||||
 | 
					                            dst: MacAddr::BROADCAST,
 | 
				
			||||||
 | 
					                            src: interface.mac,
 | 
				
			||||||
 | 
					                            ethertype: n16::new(0x800),
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        data: ip.to_bytes()
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    interface.ip_file.write(&frame.to_bytes()).map_err(|err| err.into_sys())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return Ok(buf.len());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Err(Error::new(EADDRNOTAVAIL))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(Error::new(EINVAL))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fevent(&mut self, file: usize, flags: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn close(&mut self, file: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        let handle = self.handles.remove(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        drop(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    thread::spawn(move || {
 | 
					    thread::spawn(move || {
 | 
				
			||||||
        let mut socket = File::create(":ip").expect("ipd: failed to create ip scheme");
 | 
					        let scheme_fd = syscall::open(":ip", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ipd: failed to create :ip");
 | 
				
			||||||
        let scheme = IpScheme::new();
 | 
					        let scheme_file = unsafe { File::from_raw_fd(scheme_fd) };
 | 
				
			||||||
        loop {
 | 
					
 | 
				
			||||||
            let mut packet = Packet::default();
 | 
					        let ipd = Rc::new(RefCell::new(Ipd::new(scheme_file)));
 | 
				
			||||||
            socket.read(&mut packet).expect("ipd: failed to read events from ip scheme");
 | 
					
 | 
				
			||||||
            scheme.handle(&mut packet);
 | 
					        let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue");
 | 
				
			||||||
            socket.write(&packet).expect("ipd: failed to write responses to ip scheme");
 | 
					
 | 
				
			||||||
 | 
					        //TODO: Multiple interfaces
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            let arp_fd = syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ipd: failed to open ethernet:806");
 | 
				
			||||||
 | 
					            let ip_fd = syscall::open("ethernet:800", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ipd: failed to open ethernet:800");
 | 
				
			||||||
 | 
					            let if_id = {
 | 
				
			||||||
 | 
					                let mut ipd = ipd.borrow_mut();
 | 
				
			||||||
 | 
					                let if_id = ipd.interfaces.len();
 | 
				
			||||||
 | 
					                ipd.interfaces.push(Interface::new(arp_fd, ip_fd));
 | 
				
			||||||
 | 
					                if_id
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let arp_ipd = ipd.clone();
 | 
				
			||||||
 | 
					            event_queue.add(arp_fd, move |_count: usize| -> io::Result<Option<()>> {
 | 
				
			||||||
 | 
					                arp_ipd.borrow_mut().arp_event(if_id)?;
 | 
				
			||||||
 | 
					                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<Option<()>> {
 | 
				
			||||||
 | 
					                ip_ipd.borrow_mut().ip_event(if_id)?;
 | 
				
			||||||
 | 
					                Ok(None)
 | 
				
			||||||
 | 
					            }).expect("ipd: failed to listen to events on ethernet:800");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        event_queue.add(scheme_fd, move |_count: usize| -> io::Result<Option<()>> {
 | 
				
			||||||
 | 
					            ipd.borrow_mut().scheme_event()?;
 | 
				
			||||||
 | 
					            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");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[cfg(test)]
 | 
					 | 
				
			||||||
fn test() {
 | 
					 | 
				
			||||||
    use scheme::IpScheme;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("* Test that we can read a simple packet from the same connection.");
 | 
					 | 
				
			||||||
    let bytes = "TEST".as_bytes();
 | 
					 | 
				
			||||||
    let mut scheme = IpScheme::new();
 | 
					 | 
				
			||||||
    let a = scheme.open(&"ip:127.0.0.1/11".as_bytes(), 0, 0, 0).unwrap();
 | 
					 | 
				
			||||||
    let num_bytes_written = scheme.write(a, bytes).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_written, bytes.len());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let mut buf = [0;65536];
 | 
					 | 
				
			||||||
    let num_bytes_read = scheme.read(a, &mut buf).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_read, num_bytes_written);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let bytes_read = &buf[0..num_bytes_read];
 | 
					 | 
				
			||||||
    assert_eq!(bytes, bytes_read);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("* Test that the loopback is now empty.");
 | 
					 | 
				
			||||||
    let num_bytes_read = scheme.read(a, &mut buf).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_read, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("* Test that we can read the same packet from a different connection.");
 | 
					 | 
				
			||||||
    let num_bytes_written = scheme.write(a, bytes).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_written, bytes.len());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let b = scheme.open("ip:127.0.0.1/11".as_bytes(), 0, 0, 0).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let num_bytes_read = scheme.read(b, &mut buf).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_read, num_bytes_written);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let bytes_read = &buf[0..num_bytes_read];
 | 
					 | 
				
			||||||
    assert_eq!(bytes, bytes_read);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("* Test that the loopback is now empty for both connections.");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let num_bytes_read = scheme.read(a, &mut buf).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_read, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let num_bytes_read = scheme.read(b, &mut buf).unwrap();
 | 
					 | 
				
			||||||
    assert_eq!(num_bytes_read, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("* Push a number of packets, check that we get them in the right order.");
 | 
					 | 
				
			||||||
    let mut payloads : Vec<String> = (0..100).map(|i| format!("TEST {}", i)).collect();
 | 
					 | 
				
			||||||
    for payload in &payloads {
 | 
					 | 
				
			||||||
        let bytes = payload.into_bytes();
 | 
					 | 
				
			||||||
        let num_bytes_written = scheme.write(a, &bytes).unwrap();
 | 
					 | 
				
			||||||
        assert_eq!(bytes.len(), num_bytes_written);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    for payload in &payloads {
 | 
					 | 
				
			||||||
        let bytes = payload.into_bytes();
 | 
					 | 
				
			||||||
        let mut buf = [0;65536];
 | 
					 | 
				
			||||||
        let num_bytes_read = scheme.read(a, &mut buf).unwrap();
 | 
					 | 
				
			||||||
        assert_eq!(bytes.len(), num_bytes_read);
 | 
					 | 
				
			||||||
        let bytes_read = &buf[0..num_bytes_read];
 | 
					 | 
				
			||||||
        assert_eq!(bytes, bytes_read);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,242 +0,0 @@
 | 
				
			||||||
use std::cell::RefCell;
 | 
					 | 
				
			||||||
use std::{cmp, mem};
 | 
					 | 
				
			||||||
use std::collections::VecDeque;
 | 
					 | 
				
			||||||
use std::rc::Rc;
 | 
					 | 
				
			||||||
use std::sync::Mutex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{n16, Ipv4Addr, Checksum, Ipv4Header, Ipv4};
 | 
					 | 
				
			||||||
use resource_scheme::Resource;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Max number of bytes in a packet.
 | 
					 | 
				
			||||||
const MAX_PACKET_LENGTH : usize = 65536;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// A IP (internet protocol) resource.
 | 
					 | 
				
			||||||
///
 | 
					 | 
				
			||||||
/// Each instance represents a connection (~ a IP socket).
 | 
					 | 
				
			||||||
pub struct IpResource {
 | 
					 | 
				
			||||||
    /// The underlying mechanism ensured to connect to the peer.
 | 
					 | 
				
			||||||
    pub connection: Connection,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// The IP address of the host (i.e. this machine).
 | 
					 | 
				
			||||||
    pub host_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// The IP address of the peer (i.e. the other machine).
 | 
					 | 
				
			||||||
    pub peer_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// The IP protocol used by this connection. See
 | 
					 | 
				
			||||||
    /// http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
 | 
					 | 
				
			||||||
    /// for the list of valid protocols.
 | 
					 | 
				
			||||||
    pub proto: u8,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// The id of the next packet being sent.
 | 
					 | 
				
			||||||
    /// See https://en.wikipedia.org/wiki/IPv4#Identification .
 | 
					 | 
				
			||||||
    pub id: u16,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub enum Connection {
 | 
					 | 
				
			||||||
    Device {
 | 
					 | 
				
			||||||
        /// Link to the underlying device (typically, an Ethernet card).
 | 
					 | 
				
			||||||
        link: usize,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// If this connection was opened waiting for a peer (i.e. `ip:/protocol`),
 | 
					 | 
				
			||||||
        /// the data received when the peer actually connected. Otherwise, empty.
 | 
					 | 
				
			||||||
        /// Emptied during the first call to `read()`.
 | 
					 | 
				
			||||||
        init_data: Vec<u8>,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    Loopback {
 | 
					 | 
				
			||||||
        /// FIFO queue of packets written to the loopback and waiting to be read.
 | 
					 | 
				
			||||||
        ///
 | 
					 | 
				
			||||||
        /// The data stored contains the exact data that has been added by the client
 | 
					 | 
				
			||||||
        /// calling `write()`, without adding any headers.
 | 
					 | 
				
			||||||
        ///
 | 
					 | 
				
			||||||
        /// This buffer is shared between all loopback connections.
 | 
					 | 
				
			||||||
        packets: Rc<RefCell<VecDeque<Vec<u8>>>>
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Resource for IpResource {
 | 
					 | 
				
			||||||
    /// Duplicate the connection.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// This duplicates both `self.link` and `self.init_data`.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Errors
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Fails if the `link` to the underlying device cannot be
 | 
					 | 
				
			||||||
    /// duplicated.
 | 
					 | 
				
			||||||
    fn dup(&self) -> Result<Box<Self>> {
 | 
					 | 
				
			||||||
        use self::Connection::*;
 | 
					 | 
				
			||||||
        let connection = match self.connection {
 | 
					 | 
				
			||||||
            Loopback { ref packets }=> Loopback { packets: packets.clone() },
 | 
					 | 
				
			||||||
            Device { link, ref init_data } => {
 | 
					 | 
				
			||||||
                let link = try!(syscall::dup(link));
 | 
					 | 
				
			||||||
                let init_data = init_data.clone();
 | 
					 | 
				
			||||||
                Device {
 | 
					 | 
				
			||||||
                    link: link,
 | 
					 | 
				
			||||||
                    init_data: init_data
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        Ok(Box::new(IpResource {
 | 
					 | 
				
			||||||
            host_addr: self.host_addr,
 | 
					 | 
				
			||||||
            peer_addr: self.peer_addr,
 | 
					 | 
				
			||||||
            proto: self.proto,
 | 
					 | 
				
			||||||
            id: self.id,
 | 
					 | 
				
			||||||
            connection: connection,
 | 
					 | 
				
			||||||
        }))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Get the current path, as `ip:peer/protocol`, where `peer`
 | 
					 | 
				
			||||||
    /// is the IPv4 address of the peer and `protocol` is the hex-based
 | 
					 | 
				
			||||||
    /// number of the IP protocol used.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Note that the `peer` is specified even if the connection was initially
 | 
					 | 
				
			||||||
    /// created as `ip:/protocol`.
 | 
					 | 
				
			||||||
    fn path(&self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        let path_string = format!("ip:{}/{:X}", self.peer_addr.to_string(), self.proto);
 | 
					 | 
				
			||||||
        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()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Read data from the device.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// If some data has already been made available during the establishment
 | 
					 | 
				
			||||||
    /// of the connection, this data is (entirely) read during the first call
 | 
					 | 
				
			||||||
    /// to `read()`, without attempting to actually read from the device. This
 | 
					 | 
				
			||||||
    /// can happen only if the connection was waiting for a remote peer to connect, i.e.
 | 
					 | 
				
			||||||
    /// with a url `ip:/protocol`, without host.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// If this connection is a loopback, oldest unread packet written is read.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Errors
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Fails if the call to `syscall::read()` fails for this device.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Data loss
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// If `buf` is too small, *exceeding data is discarded*. To be sure that you read
 | 
					 | 
				
			||||||
    /// all data, you should provide a 64kb `buf`.
 | 
					 | 
				
			||||||
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        use self::Connection::*;
 | 
					 | 
				
			||||||
        match self.connection {
 | 
					 | 
				
			||||||
            Loopback { ref packets }=> {
 | 
					 | 
				
			||||||
                match packets.borrow_mut().pop_front() {
 | 
					 | 
				
			||||||
                    None => Ok(0),
 | 
					 | 
				
			||||||
                    Some(data) => {
 | 
					 | 
				
			||||||
                        for (b, d) in buf.iter_mut().zip(data.iter()) {
 | 
					 | 
				
			||||||
                            *b = *d;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        // Note: We're discarding excess `data`.
 | 
					 | 
				
			||||||
                        Ok(cmp::min(buf.len(), data.len()))
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Device { ref mut init_data, link } => {
 | 
					 | 
				
			||||||
                if !init_data.is_empty() {
 | 
					 | 
				
			||||||
                    let mut data: Vec<u8> = Vec::new();
 | 
					 | 
				
			||||||
                    mem::swap(init_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; MAX_PACKET_LENGTH];
 | 
					 | 
				
			||||||
                let count = try!(syscall::read(link, &mut bytes));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                    if packet.header.proto == self.proto &&
 | 
					 | 
				
			||||||
                       (packet.header.dst.equals(self.host_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) &&
 | 
					 | 
				
			||||||
                       (packet.header.src.equals(self.peer_addr) || self.peer_addr.equals(Ipv4Addr::BROADCAST)) {
 | 
					 | 
				
			||||||
                        for (b, d) in buf.iter_mut().zip(packet.data.iter()) {
 | 
					 | 
				
			||||||
                            *b = *d;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        return Ok(cmp::min(buf.len(), packet.data.len()));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Ok(0)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Send data to the peer.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// # Errors
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// Fails if the call to `syscall::write()` fails for this device.
 | 
					 | 
				
			||||||
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        use self::Connection::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let ip_data = Vec::from(buf);
 | 
					 | 
				
			||||||
        match self.connection {
 | 
					 | 
				
			||||||
            Loopback { ref packets } => {
 | 
					 | 
				
			||||||
                // Make sure that we're not going to store data that can't be read.
 | 
					 | 
				
			||||||
                let buf =
 | 
					 | 
				
			||||||
                    if buf.len() > MAX_PACKET_LENGTH {
 | 
					 | 
				
			||||||
                        &buf[0..MAX_PACKET_LENGTH]
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        buf
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
                packets.borrow_mut().push_back(buf.to_vec());
 | 
					 | 
				
			||||||
                return Ok(buf.len())
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Device { link, .. } => {
 | 
					 | 
				
			||||||
                self.id += 1;
 | 
					 | 
				
			||||||
                let mut ip = Ipv4 {
 | 
					 | 
				
			||||||
                    header: Ipv4Header {
 | 
					 | 
				
			||||||
                        ver_hlen: 0x40 | (mem::size_of::<Ipv4Header>() / 4 & 0xF) as u8, // No Options
 | 
					 | 
				
			||||||
                        services: 0,
 | 
					 | 
				
			||||||
                        len: n16::new((mem::size_of::<Ipv4Header>() + ip_data.len()) as u16), // No Options
 | 
					 | 
				
			||||||
                        id: n16::new(self.id),
 | 
					 | 
				
			||||||
                        flags_fragment: n16::new(0),
 | 
					 | 
				
			||||||
                        ttl: 128,
 | 
					 | 
				
			||||||
                        proto: self.proto,
 | 
					 | 
				
			||||||
                        checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
                        src: self.host_addr,
 | 
					 | 
				
			||||||
                        dst: self.peer_addr,
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                    options: Vec::new(),
 | 
					 | 
				
			||||||
                    data: ip_data,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                unsafe {
 | 
					 | 
				
			||||||
                    let header_ptr: *const Ipv4Header = &ip.header;
 | 
					 | 
				
			||||||
                    ip.header.checksum.data =
 | 
					 | 
				
			||||||
                        Checksum::compile(Checksum::sum(header_ptr as usize, mem::size_of::<Ipv4Header>()) +
 | 
					 | 
				
			||||||
                                          Checksum::sum(ip.options.as_ptr() as usize, ip.options.len()));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                match syscall::write(link, &ip.to_bytes()) {
 | 
					 | 
				
			||||||
                    Ok(_) => Ok(buf.len()),
 | 
					 | 
				
			||||||
                    Err(err) => Err(err),
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn sync(&mut self) -> Result<usize> {
 | 
					 | 
				
			||||||
        if let Connection::Device { link, .. } = self.connection {
 | 
					 | 
				
			||||||
            syscall::fsync(link)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ok(0)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Drop for IpResource {
 | 
					 | 
				
			||||||
    fn drop(&mut self) {
 | 
					 | 
				
			||||||
        if let Connection::Device { link, .. } = self.connection {
 | 
					 | 
				
			||||||
            let _ = syscall::close(link);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,193 +0,0 @@
 | 
				
			||||||
use std::cell::RefCell;
 | 
					 | 
				
			||||||
use std::collections::VecDeque;
 | 
					 | 
				
			||||||
use std::rand;
 | 
					 | 
				
			||||||
use std::rc::Rc;
 | 
					 | 
				
			||||||
use std::{str, u16};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{getcfg, n16, MacAddr, Ipv4Addr, ArpHeader, Arp, Ipv4};
 | 
					 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::{Error, Result, EACCES, ENOENT, EINVAL};
 | 
					 | 
				
			||||||
use syscall::flag::O_RDWR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use resource::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// The IP address of the localhost.
 | 
					 | 
				
			||||||
const LOCALHOST: Ipv4Addr = Ipv4Addr { bytes: [127, 0, 0, 1] };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// A ARP entry (MAC + IP)
 | 
					 | 
				
			||||||
pub struct ArpEntry {
 | 
					 | 
				
			||||||
    ip: Ipv4Addr,
 | 
					 | 
				
			||||||
    mac: MacAddr,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// A IP scheme
 | 
					 | 
				
			||||||
pub struct IpScheme {
 | 
					 | 
				
			||||||
    pub arp: RefCell<Vec<ArpEntry>>,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// FIFO queue of packets written to the loopback and waiting to be read.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// The data stored contains the exact data that has been added by the client
 | 
					 | 
				
			||||||
    /// calling `write()`, without adding any headers.
 | 
					 | 
				
			||||||
    ///
 | 
					 | 
				
			||||||
    /// This buffer is shared between all loopback connections.
 | 
					 | 
				
			||||||
    pub loopback_fifo: Rc<RefCell<VecDeque<Vec<u8>>>>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl IpScheme {
 | 
					 | 
				
			||||||
    pub fn new() -> IpScheme {
 | 
					 | 
				
			||||||
        IpScheme {
 | 
					 | 
				
			||||||
            arp: RefCell::new(Vec::new()),
 | 
					 | 
				
			||||||
            loopback_fifo: Rc::new(RefCell::new(VecDeque::new())),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ResourceScheme<IpResource> for IpScheme {
 | 
					 | 
				
			||||||
    fn open_resource(&self, url: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<Box<IpResource>> {
 | 
					 | 
				
			||||||
        if uid == 0 {
 | 
					 | 
				
			||||||
            let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
            let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
            let ip_subnet = Ipv4Addr::from_str(&getcfg("ip_subnet").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
            let ip_router = Ipv4Addr::from_str(&getcfg("ip_router").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            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(proto_string) = parts.next() {
 | 
					 | 
				
			||||||
                    let proto = u8::from_str_radix(proto_string, 16).unwrap_or(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if ! host_string.is_empty() {
 | 
					 | 
				
			||||||
                        let peer_addr = Ipv4Addr::from_str(host_string);
 | 
					 | 
				
			||||||
                        let mut route_mac = MacAddr::BROADCAST;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if ! peer_addr.equals(Ipv4Addr::BROADCAST) {
 | 
					 | 
				
			||||||
                            if peer_addr.equals(LOCALHOST) {
 | 
					 | 
				
			||||||
                                return Ok(Box::new(IpResource {
 | 
					 | 
				
			||||||
                                    connection: Connection::Loopback {
 | 
					 | 
				
			||||||
                                        packets: self.loopback_fifo.clone()
 | 
					 | 
				
			||||||
                                    },
 | 
					 | 
				
			||||||
                                    host_addr: ip_addr,
 | 
					 | 
				
			||||||
                                    peer_addr: peer_addr,
 | 
					 | 
				
			||||||
                                    proto: proto,
 | 
					 | 
				
			||||||
                                    id: (rand() % 65536) as u16,
 | 
					 | 
				
			||||||
                                }));
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let mut needs_routing = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            for octet in 0..4 {
 | 
					 | 
				
			||||||
                                let me = ip_addr.bytes[octet];
 | 
					 | 
				
			||||||
                                let mask = ip_subnet.bytes[octet];
 | 
					 | 
				
			||||||
                                let them = peer_addr.bytes[octet];
 | 
					 | 
				
			||||||
                                if me & mask != them & mask {
 | 
					 | 
				
			||||||
                                    needs_routing = true;
 | 
					 | 
				
			||||||
                                    break;
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let route_addr = if needs_routing {
 | 
					 | 
				
			||||||
                                ip_router
 | 
					 | 
				
			||||||
                            } else {
 | 
					 | 
				
			||||||
                                peer_addr
 | 
					 | 
				
			||||||
                            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            for entry in self.arp.borrow().iter() {
 | 
					 | 
				
			||||||
                                if entry.ip.equals(route_addr) {
 | 
					 | 
				
			||||||
                                    route_mac = entry.mac;
 | 
					 | 
				
			||||||
                                    break;
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            if route_mac.equals(MacAddr::BROADCAST) {
 | 
					 | 
				
			||||||
                                if let Ok(link) = syscall::open(&format!("ethernet:{}/806", &route_mac.to_string()), O_RDWR) {
 | 
					 | 
				
			||||||
                                    let arp = Arp {
 | 
					 | 
				
			||||||
                                        header: ArpHeader {
 | 
					 | 
				
			||||||
                                            htype: n16::new(1),
 | 
					 | 
				
			||||||
                                            ptype: n16::new(0x800),
 | 
					 | 
				
			||||||
                                            hlen: 6,
 | 
					 | 
				
			||||||
                                            plen: 4,
 | 
					 | 
				
			||||||
                                            oper: n16::new(1),
 | 
					 | 
				
			||||||
                                            src_mac: mac_addr,
 | 
					 | 
				
			||||||
                                            src_ip: ip_addr,
 | 
					 | 
				
			||||||
                                            dst_mac: route_mac,
 | 
					 | 
				
			||||||
                                            dst_ip: route_addr,
 | 
					 | 
				
			||||||
                                        },
 | 
					 | 
				
			||||||
                                        data: Vec::new(),
 | 
					 | 
				
			||||||
                                    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    match syscall::write(link, &arp.to_bytes()) {
 | 
					 | 
				
			||||||
                                        Ok(_) => loop {
 | 
					 | 
				
			||||||
                                            let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                                            match syscall::read(link, &mut bytes) {
 | 
					 | 
				
			||||||
                                                Ok(count) => if let Some(packet) = Arp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                                                    if packet.header.oper.get() == 2 &&
 | 
					 | 
				
			||||||
                                                       packet.header.src_ip.equals(route_addr) {
 | 
					 | 
				
			||||||
                                                        route_mac = packet.header.src_mac;
 | 
					 | 
				
			||||||
                                                        self.arp.borrow_mut().push(ArpEntry {
 | 
					 | 
				
			||||||
                                                            ip: route_addr,
 | 
					 | 
				
			||||||
                                                            mac: route_mac,
 | 
					 | 
				
			||||||
                                                        });
 | 
					 | 
				
			||||||
                                                        break;
 | 
					 | 
				
			||||||
                                                    }
 | 
					 | 
				
			||||||
                                                },
 | 
					 | 
				
			||||||
                                                Err(_) => (),
 | 
					 | 
				
			||||||
                                            }
 | 
					 | 
				
			||||||
                                        },
 | 
					 | 
				
			||||||
                                        Err(err) => println!("IP: ARP Write Failed: {}", err),
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if let Ok(link) = syscall::open(&format!("ethernet:{}/800", &route_mac.to_string()), O_RDWR) {
 | 
					 | 
				
			||||||
                            return Ok(Box::new(IpResource {
 | 
					 | 
				
			||||||
                                connection: Connection::Device {
 | 
					 | 
				
			||||||
                                    link: link,
 | 
					 | 
				
			||||||
                                    init_data: Vec::new(),
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                                host_addr: ip_addr,
 | 
					 | 
				
			||||||
                                peer_addr: peer_addr,
 | 
					 | 
				
			||||||
                                proto: proto,
 | 
					 | 
				
			||||||
                                id: (rand() % 65536) as u16,
 | 
					 | 
				
			||||||
                            }));
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        while let Ok(link) = syscall::open("ethernet:/800", O_RDWR) {
 | 
					 | 
				
			||||||
                            let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                            // FIXME: Blocking call?
 | 
					 | 
				
			||||||
                            match syscall::read(link, &mut bytes) {
 | 
					 | 
				
			||||||
                                Ok(count) => {
 | 
					 | 
				
			||||||
                                    if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                                        if packet.header.proto == proto &&
 | 
					 | 
				
			||||||
                                           (packet.header.dst.equals(ip_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) {
 | 
					 | 
				
			||||||
                                            return Ok(Box::new(IpResource {
 | 
					 | 
				
			||||||
                                                connection: Connection::Device {
 | 
					 | 
				
			||||||
                                                    link: link,
 | 
					 | 
				
			||||||
                                                    init_data: packet.data,
 | 
					 | 
				
			||||||
                                                },
 | 
					 | 
				
			||||||
                                                host_addr: ip_addr,
 | 
					 | 
				
			||||||
                                                peer_addr: packet.header.src,
 | 
					 | 
				
			||||||
                                                proto: proto,
 | 
					 | 
				
			||||||
                                                id: (rand() % 65536) as u16,
 | 
					 | 
				
			||||||
                                            }));
 | 
					 | 
				
			||||||
                                        }
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                                Err(_) => break,
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    println!("IP: No protocol provided");
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                println!("IP: No host provided");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Err(Error::new(ENOENT))
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Err(Error::new(EACCES))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 601c5685f058c9276d896262195b50c75a6d7a97
 | 
					Subproject commit 1d554eda337b9d75a4c0b209c3b399b8f1148f35
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@ impl Scheme for RandScheme {
 | 
				
			||||||
        Ok(0)
 | 
					        Ok(0)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dup(&self, file: usize) -> Result<usize> {
 | 
					    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Ok(file)
 | 
					        Ok(file)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
Subproject commit 3dcaad55fe6e82450c1691da5d515861a7deed0a
 | 
					Subproject commit ec00f58d73de142332e80d097e32f3d93c2a33bf
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ name = "tcpd"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					event = { path = "../../crates/event/" }
 | 
				
			||||||
netutils = { path = "../../programs/netutils/" }
 | 
					netutils = { path = "../../programs/netutils/" }
 | 
				
			||||||
resource_scheme = { path = "../../crates/resource_scheme/" }
 | 
					rand = { git = "https://github.com/redox-os/rand.git" }
 | 
				
			||||||
syscall = { path = "../../syscall/" }
 | 
					syscall = { path = "../../syscall/" }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,30 +1,680 @@
 | 
				
			||||||
#![feature(rand)]
 | 
					extern crate event;
 | 
				
			||||||
 | 
					 | 
				
			||||||
extern crate netutils;
 | 
					extern crate netutils;
 | 
				
			||||||
extern crate resource_scheme;
 | 
					extern crate rand;
 | 
				
			||||||
extern crate syscall;
 | 
					extern crate syscall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use rand::{Rng, OsRng};
 | 
				
			||||||
 | 
					use std::collections::{BTreeMap, VecDeque};
 | 
				
			||||||
 | 
					use std::cell::RefCell;
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::{Read, Write};
 | 
					use std::io::{self, Read, Write};
 | 
				
			||||||
use std::thread;
 | 
					use std::{mem, slice, str, thread};
 | 
				
			||||||
 | 
					use std::os::unix::io::FromRawFd;
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					use event::EventQueue;
 | 
				
			||||||
use syscall::Packet;
 | 
					use netutils::{n16, n32, Ipv4, Ipv4Addr, Ipv4Header, Tcp, TcpHeader, Checksum, TCP_FIN, TCP_SYN, TCP_RST, TCP_PSH, TCP_ACK};
 | 
				
			||||||
 | 
					use syscall::data::Packet;
 | 
				
			||||||
 | 
					use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EINVAL, EISCONN, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
 | 
				
			||||||
 | 
					use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK};
 | 
				
			||||||
 | 
					use syscall::scheme::SchemeMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use scheme::TcpScheme;
 | 
					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::<u16>().unwrap_or(0);
 | 
				
			||||||
 | 
					    (host, port)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod resource;
 | 
					#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 | 
				
			||||||
mod scheme;
 | 
					enum State {
 | 
				
			||||||
 | 
					    Listen,
 | 
				
			||||||
 | 
					    SynSent,
 | 
				
			||||||
 | 
					    SynReceived,
 | 
				
			||||||
 | 
					    Established,
 | 
				
			||||||
 | 
					    FinWait1,
 | 
				
			||||||
 | 
					    FinWait2,
 | 
				
			||||||
 | 
					    CloseWait,
 | 
				
			||||||
 | 
					    Closing,
 | 
				
			||||||
 | 
					    LastAck,
 | 
				
			||||||
 | 
					    TimeWait,
 | 
				
			||||||
 | 
					    Closed
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Handle {
 | 
				
			||||||
 | 
					    local: (Ipv4Addr, u16),
 | 
				
			||||||
 | 
					    remote: (Ipv4Addr, u16),
 | 
				
			||||||
 | 
					    flags: usize,
 | 
				
			||||||
 | 
					    events: usize,
 | 
				
			||||||
 | 
					    state: State,
 | 
				
			||||||
 | 
					    seq: u32,
 | 
				
			||||||
 | 
					    ack: u32,
 | 
				
			||||||
 | 
					    data: VecDeque<(Ipv4, Tcp)>,
 | 
				
			||||||
 | 
					    todo_dup: VecDeque<Packet>,
 | 
				
			||||||
 | 
					    todo_read: VecDeque<Packet>,
 | 
				
			||||||
 | 
					    todo_write: VecDeque<Packet>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Handle {
 | 
				
			||||||
 | 
					    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<u8>) -> 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::<TcpHeader>() << 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<u8>) -> Ipv4 {
 | 
				
			||||||
 | 
					        Ipv4 {
 | 
				
			||||||
 | 
					            header: Ipv4Header {
 | 
				
			||||||
 | 
					                ver_hlen: 0x45,
 | 
				
			||||||
 | 
					                services: 0,
 | 
				
			||||||
 | 
					                len: n16::new((data.len() + mem::size_of::<Ipv4Header>()) as u16),
 | 
				
			||||||
 | 
					                id: n16::new(id),
 | 
				
			||||||
 | 
					                flags_fragment: n16::new(0),
 | 
				
			||||||
 | 
					                ttl: 127,
 | 
				
			||||||
 | 
					                proto: 0x06,
 | 
				
			||||||
 | 
					                checksum: Checksum { data: 0 },
 | 
				
			||||||
 | 
					                src: self.local.0,
 | 
				
			||||||
 | 
					                dst: self.remote.0
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            options: Vec::new(),
 | 
				
			||||||
 | 
					            data: data
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Tcpd {
 | 
				
			||||||
 | 
					    scheme_file: File,
 | 
				
			||||||
 | 
					    tcp_file: File,
 | 
				
			||||||
 | 
					    ports: BTreeMap<u16, usize>,
 | 
				
			||||||
 | 
					    next_id: usize,
 | 
				
			||||||
 | 
					    handles: BTreeMap<usize, Handle>,
 | 
				
			||||||
 | 
					    rng: OsRng,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Tcpd {
 | 
				
			||||||
 | 
					    fn new(scheme_file: File, tcp_file: File) -> Self {
 | 
				
			||||||
 | 
					        Tcpd {
 | 
				
			||||||
 | 
					            scheme_file: scheme_file,
 | 
				
			||||||
 | 
					            tcp_file: tcp_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) {
 | 
				
			||||||
 | 
					                    match a {
 | 
				
			||||||
 | 
					                        syscall::number::SYS_DUP => {
 | 
				
			||||||
 | 
					                            packet.a = a;
 | 
				
			||||||
 | 
					                            handle.todo_dup.push_back(packet);
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        syscall::number::SYS_READ => {
 | 
				
			||||||
 | 
					                            packet.a = a;
 | 
				
			||||||
 | 
					                            handle.todo_read.push_back(packet);
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                        syscall::number::SYS_WRITE => {
 | 
				
			||||||
 | 
					                            packet.a = a;
 | 
				
			||||||
 | 
					                            handle.todo_write.push_back(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 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 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, tcp)) = handle.data.pop_front() {
 | 
				
			||||||
 | 
					                                    let mut i = 0;
 | 
				
			||||||
 | 
					                                    while i < buf.len() && i < tcp.data.len() {
 | 
				
			||||||
 | 
					                                        buf[i] = tcp.data[i];
 | 
				
			||||||
 | 
					                                        i += 1;
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    packet.a = i;
 | 
				
			||||||
 | 
					                                } else {
 | 
				
			||||||
 | 
					                                    packet.a = 0;
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                self.scheme_file.write(&packet)?;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            if ! handle.todo_write.is_empty() && handle.state == State::Established {
 | 
				
			||||||
 | 
					                                let 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| err.into_sys());
 | 
				
			||||||
 | 
					                                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 {
 | 
				
			||||||
 | 
					                        let 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 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 = Handle {
 | 
				
			||||||
 | 
					                                        local: handle.local,
 | 
				
			||||||
 | 
					                                        remote: (ip.header.src, tcp.header.src.get()),
 | 
				
			||||||
 | 
					                                        flags: handle.flags,
 | 
				
			||||||
 | 
					                                        events: 0,
 | 
				
			||||||
 | 
					                                        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, new_handle));
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        for (packet, new_handle) in new_handles {
 | 
				
			||||||
 | 
					                            self.handles.insert(packet.a, new_handle);
 | 
				
			||||||
 | 
					                            self.scheme_file.write(&packet)?;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl SchemeMut for Tcpd {
 | 
				
			||||||
 | 
					    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
 | 
				
			||||||
 | 
					        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));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut handle = Handle {
 | 
				
			||||||
 | 
					            local: local,
 | 
				
			||||||
 | 
					            remote: remote,
 | 
				
			||||||
 | 
					            flags: flags,
 | 
				
			||||||
 | 
					            events: 0,
 | 
				
			||||||
 | 
					            state: State::Listen,
 | 
				
			||||||
 | 
					            seq: 0,
 | 
				
			||||||
 | 
					            ack: 0,
 | 
				
			||||||
 | 
					            data: VecDeque::new(),
 | 
				
			||||||
 | 
					            todo_dup: VecDeque::new(),
 | 
				
			||||||
 | 
					            todo_read: VecDeque::new(),
 | 
				
			||||||
 | 
					            todo_write: VecDeque::new(),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if handle.is_connected() {
 | 
				
			||||||
 | 
					            handle.seq = self.rng.gen();
 | 
				
			||||||
 | 
					            handle.ack = 0;
 | 
				
			||||||
 | 
					            handle.state = State::SynSent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let tcp = handle.create_tcp(TCP_SYN, Vec::new());
 | 
				
			||||||
 | 
					            let ip = handle.create_ip(self.rng.gen(), tcp.to_bytes());
 | 
				
			||||||
 | 
					            self.tcp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            handle.seq += 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.ports.insert(local.1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let id = self.next_id;
 | 
				
			||||||
 | 
					        self.next_id += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.handles.insert(id, handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn dup(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
 | 
					        let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let handle = {
 | 
				
			||||||
 | 
					            let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let mut new_handle = Handle {
 | 
				
			||||||
 | 
					                local: handle.local,
 | 
				
			||||||
 | 
					                remote: handle.remote,
 | 
				
			||||||
 | 
					                flags: handle.flags,
 | 
				
			||||||
 | 
					                events: 0,
 | 
				
			||||||
 | 
					                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 == "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| err.into_sys()).and(Ok(buf.len()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    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
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else if path.is_empty() {
 | 
				
			||||||
 | 
					                new_handle.data = handle.data.clone();
 | 
				
			||||||
 | 
					            } else if handle.is_connected() {
 | 
				
			||||||
 | 
					                return Err(Error::new(EISCONN));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                new_handle.remote = parse_socket(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if new_handle.is_connected() {
 | 
				
			||||||
 | 
					                    new_handle.seq = self.rng.gen();
 | 
				
			||||||
 | 
					                    new_handle.ack = 0;
 | 
				
			||||||
 | 
					                    new_handle.state = State::SynSent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    handle.data.retain(|&(ref ip, ref tcp)| {
 | 
				
			||||||
 | 
					                        if new_handle.matches(ip, tcp) {
 | 
				
			||||||
 | 
					                            new_handle.data.push_back((ip.clone(), tcp.clone()));
 | 
				
			||||||
 | 
					                            false
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            true
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    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| err.into_sys()).and(Ok(buf.len()))?;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return Err(Error::new(EINVAL));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            new_handle
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some(mut port) = self.ports.get_mut(&handle.local.1) {
 | 
				
			||||||
 | 
					            *port = *port + 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ! handle.is_connected() {
 | 
				
			||||||
 | 
					            Err(Error::new(ENOTCONN))
 | 
				
			||||||
 | 
					        } else if let Some((_ip, tcp)) = handle.data.pop_front() {
 | 
				
			||||||
 | 
					            let mut i = 0;
 | 
				
			||||||
 | 
					            while i < buf.len() && i < tcp.data.len() {
 | 
				
			||||||
 | 
					                buf[i] = tcp.data[i];
 | 
				
			||||||
 | 
					                i += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Ok(i)
 | 
				
			||||||
 | 
					        } else if handle.flags & O_NONBLOCK == O_NONBLOCK || handle.read_closed() {
 | 
				
			||||||
 | 
					            Ok(0)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Err(Error::new(EWOULDBLOCK))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn write(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
 | 
					        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ! handle.is_connected() {
 | 
				
			||||||
 | 
					            Err(Error::new(ENOTCONN))
 | 
				
			||||||
 | 
					        } else if buf.len() >= 65507 {
 | 
				
			||||||
 | 
					            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| err.into_sys())?;
 | 
				
			||||||
 | 
					                    handle.seq += buf.len() as u32;
 | 
				
			||||||
 | 
					                    Ok(buf.len())
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                _ => {
 | 
				
			||||||
 | 
					                    Err(Error::new(EWOULDBLOCK))
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fevent(&mut self, file: usize, flags: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        let handle = self.handles.get(&id).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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fsync(&mut self, file: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn close(&mut self, file: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let closed = {
 | 
				
			||||||
 | 
					            let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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| err.into_sys())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    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| err.into_sys())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    handle.seq += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    false
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                _ => true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if closed {
 | 
				
			||||||
 | 
					            let 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 main() {
 | 
					fn main() {
 | 
				
			||||||
    thread::spawn(move || {
 | 
					    thread::spawn(move || {
 | 
				
			||||||
        let mut socket = File::create(":tcp").expect("tcpd: failed to create tcp scheme");
 | 
					        let scheme_fd = syscall::open(":tcp", O_RDWR | O_CREAT | O_NONBLOCK).expect("tcpd: failed to create :tcp");
 | 
				
			||||||
        let scheme = TcpScheme;
 | 
					        let scheme_file = unsafe { File::from_raw_fd(scheme_fd) };
 | 
				
			||||||
        loop {
 | 
					
 | 
				
			||||||
            let mut packet = Packet::default();
 | 
					        let tcp_fd = syscall::open("ip:6", O_RDWR | O_NONBLOCK).expect("tcpd: failed to open ip:6");
 | 
				
			||||||
            socket.read(&mut packet).expect("tcpd: failed to read events from tcp scheme");
 | 
					        let tcp_file = unsafe { File::from_raw_fd(tcp_fd) };
 | 
				
			||||||
            scheme.handle(&mut packet);
 | 
					
 | 
				
			||||||
            socket.write(&packet).expect("tcpd: failed to write responses to tcp scheme");
 | 
					        let tcpd = Rc::new(RefCell::new(Tcpd::new(scheme_file, tcp_file)));
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        let mut event_queue = EventQueue::<()>::new().expect("tcpd: failed to create event queue");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let tcp_tcpd = tcpd.clone();
 | 
				
			||||||
 | 
					        event_queue.add(tcp_fd, move |_count: usize| -> io::Result<Option<()>> {
 | 
				
			||||||
 | 
					            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<Option<()>> {
 | 
				
			||||||
 | 
					            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");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,328 +0,0 @@
 | 
				
			||||||
use std::{cmp, mem};
 | 
					 | 
				
			||||||
use std::cell::UnsafeCell;
 | 
					 | 
				
			||||||
use std::sync::Arc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{n16, n32, Ipv4Addr, Checksum, Tcp, TcpHeader, TCP_SYN, TCP_PSH, TCP_FIN, TCP_ACK};
 | 
					 | 
				
			||||||
use resource_scheme::Resource;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct TcpStream {
 | 
					 | 
				
			||||||
    pub ip: usize,
 | 
					 | 
				
			||||||
    pub host_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
    pub peer_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
    pub peer_port: u16,
 | 
					 | 
				
			||||||
    pub host_port: u16,
 | 
					 | 
				
			||||||
    pub sequence: u32,
 | 
					 | 
				
			||||||
    pub acknowledge: u32,
 | 
					 | 
				
			||||||
    pub finished: bool
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TcpStream {
 | 
					 | 
				
			||||||
    fn path(&self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        let path_string = format!("tcp:{}:{}/{}", self.peer_addr.to_string(), self.peer_port, self.host_port);
 | 
					 | 
				
			||||||
        let path = path_string.as_bytes();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (b, p) in buf.iter_mut().zip(path.iter()) {
 | 
					 | 
				
			||||||
            *b = *p;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(cmp::min(buf.len(), path.len()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        if self.finished {
 | 
					 | 
				
			||||||
            return Ok(0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        loop {
 | 
					 | 
				
			||||||
            let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
            let count = try!(syscall::read(self.ip, &mut bytes));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                if segment.header.dst.get() == self.host_port && segment.header.src.get() == self.peer_port {
 | 
					 | 
				
			||||||
                    //println!("Read: {}=={} {:X}: {}", segment.header.sequence.get(), self.acknowledge, segment.header.flags.get(), segment.data.len());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if self.acknowledge == segment.header.sequence.get() {
 | 
					 | 
				
			||||||
                        if segment.header.flags.get() & TCP_FIN == TCP_FIN {
 | 
					 | 
				
			||||||
                            self.finished = true;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK {
 | 
					 | 
				
			||||||
                            let flags = if self.finished {
 | 
					 | 
				
			||||||
                                TCP_ACK | TCP_FIN
 | 
					 | 
				
			||||||
                            } else {
 | 
					 | 
				
			||||||
                                TCP_ACK
 | 
					 | 
				
			||||||
                            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            // Send ACK
 | 
					 | 
				
			||||||
                            self.acknowledge += segment.data.len() as u32;
 | 
					 | 
				
			||||||
                            let mut tcp = Tcp {
 | 
					 | 
				
			||||||
                                header: TcpHeader {
 | 
					 | 
				
			||||||
                                    src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                                    dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                                    sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                                    ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                                    flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | flags),
 | 
					 | 
				
			||||||
                                    window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                                    checksum: Checksum {
 | 
					 | 
				
			||||||
                                        data: 0
 | 
					 | 
				
			||||||
                                    },
 | 
					 | 
				
			||||||
                                    urgent_pointer: n16::new(0)
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                                options: Vec::new(),
 | 
					 | 
				
			||||||
                                data: Vec::new()
 | 
					 | 
				
			||||||
                            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            //println!("Sending read ack: {} {} {:X}", tcp.header.sequence.get(), tcp.header.ack_num.get(), tcp.header.flags.get());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let _ = syscall::write(self.ip, &tcp.to_bytes());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            // TODO: Support broken packets (one packet in two buffers)
 | 
					 | 
				
			||||||
                            let mut i = 0;
 | 
					 | 
				
			||||||
                            while i < buf.len() && i < segment.data.len() {
 | 
					 | 
				
			||||||
                                buf[i] = segment.data[i];
 | 
					 | 
				
			||||||
                                i += 1;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            return Ok(i);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        println!("TCP: MISMATCH: {}=={}", segment.header.sequence.get(), self.acknowledge);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    println!("TCP: WRONG PORT {}=={} && {}=={}", segment.header.dst.get(), self.host_port, segment.header.src.get(), self.peer_port);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        let tcp_data = Vec::from(buf);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut tcp = Tcp {
 | 
					 | 
				
			||||||
            header: TcpHeader {
 | 
					 | 
				
			||||||
                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                flags: n16::new((((mem::size_of::<TcpHeader>()) << 10) & 0xF000) as u16 | TCP_PSH |
 | 
					 | 
				
			||||||
                                TCP_ACK),
 | 
					 | 
				
			||||||
                window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
                urgent_pointer: n16::new(0),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            options: Vec::new(),
 | 
					 | 
				
			||||||
            data: tcp_data,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match syscall::write(self.ip, &tcp.to_bytes()) {
 | 
					 | 
				
			||||||
            Ok(size) => {
 | 
					 | 
				
			||||||
                loop {
 | 
					 | 
				
			||||||
                    // Wait for ACK
 | 
					 | 
				
			||||||
                    let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                    match syscall::read(self.ip, &mut bytes) {
 | 
					 | 
				
			||||||
                        Ok(count) => {
 | 
					 | 
				
			||||||
                            if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                                if segment.header.dst.get() == self.host_port &&
 | 
					 | 
				
			||||||
                                   segment.header.src.get() == self.peer_port {
 | 
					 | 
				
			||||||
                                    return if (segment.header.flags.get() & (TCP_SYN | TCP_ACK)) == TCP_ACK {
 | 
					 | 
				
			||||||
                                        self.sequence = segment.header.ack_num.get();
 | 
					 | 
				
			||||||
                                        self.acknowledge = segment.header.sequence.get();
 | 
					 | 
				
			||||||
                                        Ok(size)
 | 
					 | 
				
			||||||
                                    } else {
 | 
					 | 
				
			||||||
                                        Err(Error::new(EPIPE))
 | 
					 | 
				
			||||||
                                    };
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        Err(err) => return Err(err),
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Err(err) => Err(err),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn sync(&mut self) -> Result<usize> {
 | 
					 | 
				
			||||||
        syscall::fsync(self.ip)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Etablish client
 | 
					 | 
				
			||||||
    pub fn client_establish(&mut self) -> bool {
 | 
					 | 
				
			||||||
        // Send SYN
 | 
					 | 
				
			||||||
        let mut tcp = Tcp {
 | 
					 | 
				
			||||||
            header: TcpHeader {
 | 
					 | 
				
			||||||
                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_SYN),
 | 
					 | 
				
			||||||
                window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
                urgent_pointer: n16::new(0),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            options: Vec::new(),
 | 
					 | 
				
			||||||
            data: Vec::new(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match syscall::write(self.ip, &tcp.to_bytes()) {
 | 
					 | 
				
			||||||
            Ok(_) => {
 | 
					 | 
				
			||||||
                loop {
 | 
					 | 
				
			||||||
                    // Wait for SYN-ACK
 | 
					 | 
				
			||||||
                    let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                    match syscall::read(self.ip, &mut bytes) {
 | 
					 | 
				
			||||||
                        Ok(count) => {
 | 
					 | 
				
			||||||
                            if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                                if segment.header.dst.get() == self.host_port &&
 | 
					 | 
				
			||||||
                                   segment.header.src.get() == self.peer_port {
 | 
					 | 
				
			||||||
                                    return if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN | TCP_ACK {
 | 
					 | 
				
			||||||
                                        self.sequence = segment.header.ack_num.get();
 | 
					 | 
				
			||||||
                                        self.acknowledge = segment.header.sequence.get();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        self.acknowledge += 1;
 | 
					 | 
				
			||||||
                                        tcp = Tcp {
 | 
					 | 
				
			||||||
                                            header: TcpHeader {
 | 
					 | 
				
			||||||
                                                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                                                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                                                sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                                                ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                                                flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_ACK),
 | 
					 | 
				
			||||||
                                                window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                                                checksum: Checksum {
 | 
					 | 
				
			||||||
                                                    data: 0
 | 
					 | 
				
			||||||
                                                },
 | 
					 | 
				
			||||||
                                                urgent_pointer: n16::new(0)
 | 
					 | 
				
			||||||
                                            },
 | 
					 | 
				
			||||||
                                            options: Vec::new(),
 | 
					 | 
				
			||||||
                                            data: Vec::new()
 | 
					 | 
				
			||||||
                                        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        let _ = syscall::write(self.ip, &tcp.to_bytes());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                        true
 | 
					 | 
				
			||||||
                                    } else {
 | 
					 | 
				
			||||||
                                        false
 | 
					 | 
				
			||||||
                                    };
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        Err(_) => return false,
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Err(_) => false,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Try to establish a server connection
 | 
					 | 
				
			||||||
    pub fn server_establish(&mut self, _: Tcp) -> bool {
 | 
					 | 
				
			||||||
        // Send SYN-ACK
 | 
					 | 
				
			||||||
        self.acknowledge += 1;
 | 
					 | 
				
			||||||
        let mut tcp = Tcp {
 | 
					 | 
				
			||||||
            header: TcpHeader {
 | 
					 | 
				
			||||||
                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                flags: n16::new(((mem::size_of::<TcpHeader>() << 10) & 0xF000) as u16 | TCP_SYN |
 | 
					 | 
				
			||||||
                                TCP_ACK),
 | 
					 | 
				
			||||||
                window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
                urgent_pointer: n16::new(0),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            options: Vec::new(),
 | 
					 | 
				
			||||||
            data: Vec::new(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match syscall::write(self.ip, &tcp.to_bytes()) {
 | 
					 | 
				
			||||||
            Ok(_) => {
 | 
					 | 
				
			||||||
                loop {
 | 
					 | 
				
			||||||
                    // Wait for ACK
 | 
					 | 
				
			||||||
                    let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                    match syscall::read(self.ip, &mut bytes) {
 | 
					 | 
				
			||||||
                        Ok(count ) => {
 | 
					 | 
				
			||||||
                            if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                                if segment.header.dst.get() == self.host_port &&
 | 
					 | 
				
			||||||
                                   segment.header.src.get() == self.peer_port {
 | 
					 | 
				
			||||||
                                    return if segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_ACK {
 | 
					 | 
				
			||||||
                                        self.sequence = segment.header.ack_num.get();
 | 
					 | 
				
			||||||
                                        self.acknowledge = segment.header.sequence.get();
 | 
					 | 
				
			||||||
                                        true
 | 
					 | 
				
			||||||
                                    } else {
 | 
					 | 
				
			||||||
                                        false
 | 
					 | 
				
			||||||
                                    };
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        Err(_) => return false,
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Err(_) => false,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Drop for TcpStream {
 | 
					 | 
				
			||||||
    fn drop(&mut self) {
 | 
					 | 
				
			||||||
        // Send FIN-ACK
 | 
					 | 
				
			||||||
        let mut tcp = Tcp {
 | 
					 | 
				
			||||||
            header: TcpHeader {
 | 
					 | 
				
			||||||
                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                sequence: n32::new(self.sequence),
 | 
					 | 
				
			||||||
                ack_num: n32::new(self.acknowledge),
 | 
					 | 
				
			||||||
                flags: n16::new((((mem::size_of::<TcpHeader>()) << 10) & 0xF000) as u16 | TCP_FIN | TCP_ACK),
 | 
					 | 
				
			||||||
                window_size: n16::new(65535),
 | 
					 | 
				
			||||||
                checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
                urgent_pointer: n16::new(0),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            options: Vec::new(),
 | 
					 | 
				
			||||||
            data: Vec::new(),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        tcp.checksum(&self.host_addr, &self.peer_addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let _ = syscall::write(self.ip, &tcp.to_bytes());
 | 
					 | 
				
			||||||
        let _ = syscall::close(self.ip);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// A TCP resource
 | 
					 | 
				
			||||||
pub struct TcpResource {
 | 
					 | 
				
			||||||
    pub stream: Arc<UnsafeCell<TcpStream>>
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Resource for TcpResource {
 | 
					 | 
				
			||||||
    fn dup(&self) -> Result<Box<TcpResource>> {
 | 
					 | 
				
			||||||
        Ok(Box::new(TcpResource {
 | 
					 | 
				
			||||||
            stream: self.stream.clone()
 | 
					 | 
				
			||||||
        }))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn path(&self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        unsafe { (*self.stream.get()).path(buf) }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        unsafe { (*self.stream.get()).read(buf) }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        unsafe { (*self.stream.get()).write(buf) }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn sync(&mut self) -> Result<usize> {
 | 
					 | 
				
			||||||
        unsafe { (*self.stream.get()).sync() }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,98 +0,0 @@
 | 
				
			||||||
use std::cell::UnsafeCell;
 | 
					 | 
				
			||||||
use std::rand;
 | 
					 | 
				
			||||||
use std::sync::Arc;
 | 
					 | 
				
			||||||
use std::{str, u16};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{getcfg, Ipv4Addr, Tcp, TCP_SYN, TCP_ACK};
 | 
					 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::{Error, Result, ENOENT, EINVAL};
 | 
					 | 
				
			||||||
use syscall::flag::O_RDWR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use resource::{TcpResource, TcpStream};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// A TCP scheme
 | 
					 | 
				
			||||||
pub struct TcpScheme;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ResourceScheme<TcpResource> for TcpScheme {
 | 
					 | 
				
			||||||
    fn open_resource(&self, url: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<Box<TcpResource>> {
 | 
					 | 
				
			||||||
        let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
 | 
					 | 
				
			||||||
        let mut parts = path.split('/');
 | 
					 | 
				
			||||||
        let remote = parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
        let path = parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut remote_parts = remote.split(':');
 | 
					 | 
				
			||||||
        let host = remote_parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
        let port = remote_parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ! host.is_empty() && ! port.is_empty() {
 | 
					 | 
				
			||||||
            let peer_addr = Ipv4Addr::from_str(host);
 | 
					 | 
				
			||||||
            let peer_port = port.parse::<u16>().unwrap_or(0);
 | 
					 | 
				
			||||||
            let host_port = (rand() % 32768 + 32768) as u16;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            match syscall::open(&format!("ip:{}/6", peer_addr.to_string()), O_RDWR) {
 | 
					 | 
				
			||||||
                Ok(ip) => {
 | 
					 | 
				
			||||||
                    let mut stream = TcpStream {
 | 
					 | 
				
			||||||
                        ip: ip,
 | 
					 | 
				
			||||||
                        host_addr: ip_addr,
 | 
					 | 
				
			||||||
                        peer_addr: peer_addr,
 | 
					 | 
				
			||||||
                        peer_port: peer_port,
 | 
					 | 
				
			||||||
                        host_port: host_port,
 | 
					 | 
				
			||||||
                        sequence: rand() as u32,
 | 
					 | 
				
			||||||
                        acknowledge: 0,
 | 
					 | 
				
			||||||
                        finished: false
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if stream.client_establish() {
 | 
					 | 
				
			||||||
                        return Ok(Box::new(TcpResource {
 | 
					 | 
				
			||||||
                            stream: Arc::new(UnsafeCell::new(stream))
 | 
					 | 
				
			||||||
                        }));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                Err(err) => return Err(err),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else if ! path.is_empty() {
 | 
					 | 
				
			||||||
            let host_port = path.parse::<u16>().unwrap_or(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            while let Ok(ip) = syscall::open("ip:/6", O_RDWR) {
 | 
					 | 
				
			||||||
                let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                match syscall::read(ip, &mut bytes) {
 | 
					 | 
				
			||||||
                    Ok(count) => {
 | 
					 | 
				
			||||||
                        if let Some(segment) = Tcp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                            if segment.header.dst.get() == host_port && segment.header.flags.get() & (TCP_SYN | TCP_ACK) == TCP_SYN {
 | 
					 | 
				
			||||||
                                let mut path = [0; 256];
 | 
					 | 
				
			||||||
                                if let Ok(path_count) = syscall::fpath(ip, &mut path) {
 | 
					 | 
				
			||||||
                                    let ip_reference = unsafe { str::from_utf8_unchecked(&path[.. path_count]) }.split(':').nth(1).unwrap_or("");
 | 
					 | 
				
			||||||
                                    let ip_remote = ip_reference.split('/').next().unwrap_or("");
 | 
					 | 
				
			||||||
                                    let peer_addr = ip_remote.split(':').next().unwrap_or("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    let mut stream = TcpStream {
 | 
					 | 
				
			||||||
                                        ip: ip,
 | 
					 | 
				
			||||||
                                        host_addr: ip_addr,
 | 
					 | 
				
			||||||
                                        peer_addr: Ipv4Addr::from_str(peer_addr),
 | 
					 | 
				
			||||||
                                        peer_port: segment.header.src.get(),
 | 
					 | 
				
			||||||
                                        host_port: host_port,
 | 
					 | 
				
			||||||
                                        sequence: rand() as u32,
 | 
					 | 
				
			||||||
                                        acknowledge: segment.header.sequence.get(),
 | 
					 | 
				
			||||||
                                        finished: false
 | 
					 | 
				
			||||||
                                    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    if stream.server_establish(segment) {
 | 
					 | 
				
			||||||
                                        return Ok(Box::new(TcpResource {
 | 
					 | 
				
			||||||
                                            stream: Arc::new(UnsafeCell::new(stream))
 | 
					 | 
				
			||||||
                                        }));
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    Err(err) => return Err(err),
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Err(Error::new(ENOENT))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ name = "udpd"
 | 
				
			||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
 | 
					event = { path = "../../crates/event/" }
 | 
				
			||||||
netutils = { path = "../../programs/netutils/" }
 | 
					netutils = { path = "../../programs/netutils/" }
 | 
				
			||||||
resource_scheme = { path = "../../crates/resource_scheme/" }
 | 
					rand = { git = "https://github.com/redox-os/rand.git" }
 | 
				
			||||||
syscall = { path = "../../syscall/" }
 | 
					syscall = { path = "../../syscall/" }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,30 +1,348 @@
 | 
				
			||||||
#![feature(rand)]
 | 
					extern crate event;
 | 
				
			||||||
 | 
					 | 
				
			||||||
extern crate netutils;
 | 
					extern crate netutils;
 | 
				
			||||||
extern crate resource_scheme;
 | 
					extern crate rand;
 | 
				
			||||||
extern crate syscall;
 | 
					extern crate syscall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use rand::{Rng, OsRng};
 | 
				
			||||||
 | 
					use std::collections::{BTreeMap, VecDeque};
 | 
				
			||||||
 | 
					use std::cell::RefCell;
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::{Read, Write};
 | 
					use std::io::{self, Read, Write};
 | 
				
			||||||
use std::thread;
 | 
					use std::{mem, slice, str, thread};
 | 
				
			||||||
 | 
					use std::os::unix::io::FromRawFd;
 | 
				
			||||||
 | 
					use std::rc::Rc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					use event::EventQueue;
 | 
				
			||||||
use syscall::Packet;
 | 
					use netutils::{n16, Ipv4, Ipv4Addr, Ipv4Header, Udp, UdpHeader, Checksum};
 | 
				
			||||||
 | 
					use syscall::data::Packet;
 | 
				
			||||||
 | 
					use syscall::error::{Error, Result, EACCES, EADDRINUSE, EBADF, EINVAL, EMSGSIZE, ENOTCONN, EWOULDBLOCK};
 | 
				
			||||||
 | 
					use syscall::flag::{EVENT_READ, O_CREAT, O_RDWR, O_NONBLOCK};
 | 
				
			||||||
 | 
					use syscall::scheme::SchemeMut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use scheme::UdpScheme;
 | 
					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::<u16>().unwrap_or(0);
 | 
				
			||||||
 | 
					    (host, port)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod resource;
 | 
					struct Handle {
 | 
				
			||||||
mod scheme;
 | 
					    local: (Ipv4Addr, u16),
 | 
				
			||||||
 | 
					    remote: (Ipv4Addr, u16),
 | 
				
			||||||
 | 
					    flags: usize,
 | 
				
			||||||
 | 
					    events: usize,
 | 
				
			||||||
 | 
					    data: VecDeque<Vec<u8>>,
 | 
				
			||||||
 | 
					    todo: VecDeque<Packet>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Udpd {
 | 
				
			||||||
 | 
					    scheme_file: File,
 | 
				
			||||||
 | 
					    udp_file: File,
 | 
				
			||||||
 | 
					    ports: BTreeMap<u16, usize>,
 | 
				
			||||||
 | 
					    next_id: usize,
 | 
				
			||||||
 | 
					    handles: BTreeMap<usize, Handle>,
 | 
				
			||||||
 | 
					    rng: OsRng,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Udpd {
 | 
				
			||||||
 | 
					    fn new(scheme_file: File, udp_file: File) -> Self {
 | 
				
			||||||
 | 
					        Udpd {
 | 
				
			||||||
 | 
					            scheme_file: scheme_file,
 | 
				
			||||||
 | 
					            udp_file: udp_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) {
 | 
				
			||||||
 | 
					                    handle.todo.push_back(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() {
 | 
				
			||||||
 | 
					                            // 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 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(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl SchemeMut for Udpd {
 | 
				
			||||||
 | 
					    fn open(&mut self, url: &[u8], flags: usize, uid: u32, _gid: u32) -> Result<usize> {
 | 
				
			||||||
 | 
					        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 {
 | 
				
			||||||
 | 
					            local: local,
 | 
				
			||||||
 | 
					            remote: remote,
 | 
				
			||||||
 | 
					            flags: flags,
 | 
				
			||||||
 | 
					            events: 0,
 | 
				
			||||||
 | 
					            data: VecDeque::new(),
 | 
				
			||||||
 | 
					            todo: VecDeque::new(),
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn dup(&mut self, file: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
 | 
					        let mut handle = {
 | 
				
			||||||
 | 
					            let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					            Handle {
 | 
				
			||||||
 | 
					                local: handle.local,
 | 
				
			||||||
 | 
					                remote: handle.remote,
 | 
				
			||||||
 | 
					                flags: handle.flags,
 | 
				
			||||||
 | 
					                events: 0,
 | 
				
			||||||
 | 
					                data: handle.data.clone(),
 | 
				
			||||||
 | 
					                todo: VecDeque::new(),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let path = str::from_utf8(buf).or(Err(Error::new(EINVAL)))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        let mut handle = self.handles.get_mut(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
 | 
				
			||||||
 | 
					            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;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            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<usize> {
 | 
				
			||||||
 | 
					        let handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if handle.remote.0 == Ipv4Addr::NULL || handle.remote.1 == 0 {
 | 
				
			||||||
 | 
					            Err(Error::new(ENOTCONN))
 | 
				
			||||||
 | 
					        } else if buf.len() >= 65507 {
 | 
				
			||||||
 | 
					            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::<UdpHeader>()) 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::<Ipv4Header>()) as u16),
 | 
				
			||||||
 | 
					                    id: n16::new(self.rng.gen()),
 | 
				
			||||||
 | 
					                    flags_fragment: n16::new(0),
 | 
				
			||||||
 | 
					                    ttl: 127,
 | 
				
			||||||
 | 
					                    proto: 0x11,
 | 
				
			||||||
 | 
					                    checksum: Checksum { data: 0 },
 | 
				
			||||||
 | 
					                    src: handle.local.0,
 | 
				
			||||||
 | 
					                    dst: handle.remote.0
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                options: Vec::new(),
 | 
				
			||||||
 | 
					                data: ip_data
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.udp_file.write(&ip.to_bytes()).map_err(|err| err.into_sys()).and(Ok(buf.len()))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fevent(&mut self, file: usize, flags: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        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<usize> {
 | 
				
			||||||
 | 
					        let handle = self.handles.get(&id).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)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fsync(&mut self, file: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        let _handle = self.handles.get(&file).ok_or(Error::new(EBADF))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn close(&mut self, file: usize) -> Result<usize> {
 | 
				
			||||||
 | 
					        let 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 {
 | 
				
			||||||
 | 
					            drop(self.ports.remove(&handle.local.1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        drop(handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
    thread::spawn(move || {
 | 
					    thread::spawn(move || {
 | 
				
			||||||
        let mut socket = File::create(":udp").expect("udpd: failed to create udp scheme");
 | 
					        let scheme_fd = syscall::open(":udp", O_RDWR | O_CREAT | O_NONBLOCK).expect("udpd: failed to create :udp");
 | 
				
			||||||
        let scheme = UdpScheme;
 | 
					        let scheme_file = unsafe { File::from_raw_fd(scheme_fd) };
 | 
				
			||||||
        loop {
 | 
					
 | 
				
			||||||
            let mut packet = Packet::default();
 | 
					        let udp_fd = syscall::open("ip:11", O_RDWR | O_NONBLOCK).expect("udpd: failed to open ip:11");
 | 
				
			||||||
            socket.read(&mut packet).expect("udpd: failed to read events from udp scheme");
 | 
					        let udp_file = unsafe { File::from_raw_fd(udp_fd) };
 | 
				
			||||||
            scheme.handle(&mut packet);
 | 
					
 | 
				
			||||||
            socket.write(&packet).expect("udpd: failed to write responses to udp scheme");
 | 
					        let udpd = Rc::new(RefCell::new(Udpd::new(scheme_file, udp_file)));
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
 | 
					        let mut event_queue = EventQueue::<()>::new().expect("udpd: failed to create event queue");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let udp_udpd = udpd.clone();
 | 
				
			||||||
 | 
					        event_queue.add(udp_fd, move |_count: usize| -> io::Result<Option<()>> {
 | 
				
			||||||
 | 
					            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<Option<()>> {
 | 
				
			||||||
 | 
					            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");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,115 +0,0 @@
 | 
				
			||||||
use std::{cmp, mem};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{n16, Ipv4Addr, Checksum, Udp, UdpHeader};
 | 
					 | 
				
			||||||
use resource_scheme::Resource;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// UDP resource
 | 
					 | 
				
			||||||
pub struct UdpResource {
 | 
					 | 
				
			||||||
    pub ip: usize,
 | 
					 | 
				
			||||||
    pub data: Vec<u8>,
 | 
					 | 
				
			||||||
    pub host_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
    pub peer_addr: Ipv4Addr,
 | 
					 | 
				
			||||||
    pub peer_port: u16,
 | 
					 | 
				
			||||||
    pub host_port: u16,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl Resource for UdpResource {
 | 
					 | 
				
			||||||
    fn dup(&self) -> Result<Box<UdpResource>> {
 | 
					 | 
				
			||||||
        match syscall::dup(self.ip) {
 | 
					 | 
				
			||||||
            Ok(ip) => {
 | 
					 | 
				
			||||||
                Ok(Box::new(UdpResource {
 | 
					 | 
				
			||||||
                    ip: ip,
 | 
					 | 
				
			||||||
                    data: self.data.clone(),
 | 
					 | 
				
			||||||
                    host_addr: self.host_addr,
 | 
					 | 
				
			||||||
                    peer_addr: self.peer_addr,
 | 
					 | 
				
			||||||
                    peer_port: self.peer_port,
 | 
					 | 
				
			||||||
                    host_port: self.host_port,
 | 
					 | 
				
			||||||
                }))
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Err(err) => Err(err),
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn path(&self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        let path_string = format!("udp:{}:{}/{}", self.peer_addr.to_string(), self.peer_port, self.host_port);
 | 
					 | 
				
			||||||
        let path = path_string.as_bytes();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (b, p) in buf.iter_mut().zip(path.iter()) {
 | 
					 | 
				
			||||||
            *b = *p;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Ok(cmp::min(buf.len(), path.len()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        if ! self.data.is_empty() {
 | 
					 | 
				
			||||||
            let mut bytes: Vec<u8> = Vec::new();
 | 
					 | 
				
			||||||
            mem::swap(&mut self.data, &mut bytes);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // TODO: Allow splitting
 | 
					 | 
				
			||||||
            let mut i = 0;
 | 
					 | 
				
			||||||
            while i < buf.len() && i < bytes.len() {
 | 
					 | 
				
			||||||
                buf[i] = bytes[i];
 | 
					 | 
				
			||||||
                i += 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return Ok(i);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        loop {
 | 
					 | 
				
			||||||
            let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
            let count = try!(syscall::read(self.ip, &mut bytes));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if let Some(datagram) = Udp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                if datagram.header.dst.get() == self.host_port &&
 | 
					 | 
				
			||||||
                   datagram.header.src.get() == self.peer_port {
 | 
					 | 
				
			||||||
                    // TODO: Allow splitting
 | 
					 | 
				
			||||||
                    let mut i = 0;
 | 
					 | 
				
			||||||
                    while i < buf.len() && i < datagram.data.len() {
 | 
					 | 
				
			||||||
                        buf[i] = datagram.data[i];
 | 
					 | 
				
			||||||
                        i += 1;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    return Ok(i);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
 | 
					 | 
				
			||||||
        let mut udp = Udp {
 | 
					 | 
				
			||||||
            header: UdpHeader {
 | 
					 | 
				
			||||||
                src: n16::new(self.host_port),
 | 
					 | 
				
			||||||
                dst: n16::new(self.peer_port),
 | 
					 | 
				
			||||||
                len: n16::new((mem::size_of::<UdpHeader>() + buf.len()) as u16),
 | 
					 | 
				
			||||||
                checksum: Checksum { data: 0 },
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            data: Vec::from(buf),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsafe {
 | 
					 | 
				
			||||||
            let proto = n16::new(0x11);
 | 
					 | 
				
			||||||
            let datagram_len = n16::new((mem::size_of::<UdpHeader>() + udp.data.len()) as u16);
 | 
					 | 
				
			||||||
            udp.header.checksum.data =
 | 
					 | 
				
			||||||
                Checksum::compile(Checksum::sum((&self.host_addr as *const Ipv4Addr) as usize,
 | 
					 | 
				
			||||||
                                                mem::size_of::<Ipv4Addr>()) +
 | 
					 | 
				
			||||||
                                  Checksum::sum((&self.peer_addr as *const Ipv4Addr) as usize,
 | 
					 | 
				
			||||||
                                                mem::size_of::<Ipv4Addr>()) +
 | 
					 | 
				
			||||||
                                  Checksum::sum((&proto as *const n16) as usize,
 | 
					 | 
				
			||||||
                                                mem::size_of::<n16>()) +
 | 
					 | 
				
			||||||
                                  Checksum::sum((&datagram_len as *const n16) as usize,
 | 
					 | 
				
			||||||
                                                mem::size_of::<n16>()) +
 | 
					 | 
				
			||||||
                                  Checksum::sum((&udp.header as *const UdpHeader) as usize,
 | 
					 | 
				
			||||||
                                                mem::size_of::<UdpHeader>()) +
 | 
					 | 
				
			||||||
                                  Checksum::sum(udp.data.as_ptr() as usize, udp.data.len()));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        syscall::write(self.ip, &udp.to_bytes()).and(Ok(buf.len()))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn sync(&mut self) -> Result<usize> {
 | 
					 | 
				
			||||||
        syscall::fsync(self.ip)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,73 +0,0 @@
 | 
				
			||||||
use std::rand;
 | 
					 | 
				
			||||||
use std::{str, u16};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use netutils::{getcfg, Ipv4Addr, Udp};
 | 
					 | 
				
			||||||
use resource_scheme::ResourceScheme;
 | 
					 | 
				
			||||||
use syscall;
 | 
					 | 
				
			||||||
use syscall::error::{Error, Result, ENOENT, EINVAL};
 | 
					 | 
				
			||||||
use syscall::flag::O_RDWR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use resource::UdpResource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// UDP UdpScheme
 | 
					 | 
				
			||||||
pub struct UdpScheme;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ResourceScheme<UdpResource> for UdpScheme {
 | 
					 | 
				
			||||||
    fn open_resource(&self, url: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<Box<UdpResource>> {
 | 
					 | 
				
			||||||
        let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
 | 
					 | 
				
			||||||
        let mut parts = path.split('/');
 | 
					 | 
				
			||||||
        let remote = parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
        let path = parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Check host and port vs path
 | 
					 | 
				
			||||||
        if remote.is_empty() {
 | 
					 | 
				
			||||||
            let host_port = path.parse::<u16>().unwrap_or(0);
 | 
					 | 
				
			||||||
            if host_port > 0 {
 | 
					 | 
				
			||||||
                while let Ok(ip) = syscall::open("ip:/11", O_RDWR) {
 | 
					 | 
				
			||||||
                    let mut bytes = [0; 65536];
 | 
					 | 
				
			||||||
                    if let Ok(count) = syscall::read(ip, &mut bytes) {
 | 
					 | 
				
			||||||
                        if let Some(datagram) = Udp::from_bytes(&bytes[..count]) {
 | 
					 | 
				
			||||||
                            if datagram.header.dst.get() == host_port {
 | 
					 | 
				
			||||||
                                let mut path = [0; 256];
 | 
					 | 
				
			||||||
                                if let Ok(path_count) = syscall::fpath(ip, &mut path) {
 | 
					 | 
				
			||||||
                                    let ip_reference = unsafe { str::from_utf8_unchecked(&path[.. path_count]) }.split(':').nth(1).unwrap_or("");
 | 
					 | 
				
			||||||
                                    let peer_addr = ip_reference.split('/').next().unwrap_or("").split(':').next().unwrap_or("");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                    return Ok(Box::new(UdpResource {
 | 
					 | 
				
			||||||
                                        ip: ip,
 | 
					 | 
				
			||||||
                                        data: datagram.data,
 | 
					 | 
				
			||||||
                                        host_addr: ip_addr,
 | 
					 | 
				
			||||||
                                        peer_addr: Ipv4Addr::from_str(peer_addr),
 | 
					 | 
				
			||||||
                                        peer_port: datagram.header.src.get(),
 | 
					 | 
				
			||||||
                                        host_port: host_port,
 | 
					 | 
				
			||||||
                                    }));
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            let mut remote_parts = remote.split(':');
 | 
					 | 
				
			||||||
            let peer_addr = remote_parts.next().unwrap_or("");
 | 
					 | 
				
			||||||
            let peer_port = remote_parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
 | 
					 | 
				
			||||||
            if peer_port > 0 {
 | 
					 | 
				
			||||||
                let host_port = path.parse::<u16>().unwrap_or((rand() % 32768 + 32768) as u16);
 | 
					 | 
				
			||||||
                if let Ok(ip) = syscall::open(&format!("ip:{}/11", peer_addr), O_RDWR) {
 | 
					 | 
				
			||||||
                    return Ok(Box::new(UdpResource {
 | 
					 | 
				
			||||||
                        ip: ip,
 | 
					 | 
				
			||||||
                        data: Vec::new(),
 | 
					 | 
				
			||||||
                        host_addr: ip_addr,
 | 
					 | 
				
			||||||
                        peer_addr: Ipv4Addr::from_str(peer_addr),
 | 
					 | 
				
			||||||
                        peer_port: peer_port as u16,
 | 
					 | 
				
			||||||
                        host_port: host_port,
 | 
					 | 
				
			||||||
                    }));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Err(Error::new(ENOENT))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -48,8 +48,8 @@ pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
 | 
				
			||||||
    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
 | 
					    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn dup(fd: usize) -> Result<usize> {
 | 
					pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
    unsafe { syscall1(SYS_DUP, fd) }
 | 
					    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> {
 | 
					pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ pub trait Scheme {
 | 
				
			||||||
            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SYS_DUP => self.dup(packet.b),
 | 
					            SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
				
			||||||
            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
					            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
				
			||||||
            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
					            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
				
			||||||
            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
					            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
				
			||||||
| 
						 | 
					@ -49,7 +49,7 @@ pub trait Scheme {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Resource operations */
 | 
					    /* Resource operations */
 | 
				
			||||||
    #[allow(unused_variables)]
 | 
					    #[allow(unused_variables)]
 | 
				
			||||||
    fn dup(&self, old_id: usize) -> Result<usize> {
 | 
					    fn dup(&self, old_id: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Err(Error::new(EBADF))
 | 
					        Err(Error::new(EBADF))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,7 +107,7 @@ pub trait SchemeMut {
 | 
				
			||||||
            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_RMDIR => self.rmdir(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
					            SYS_UNLINK => self.unlink(unsafe { slice::from_raw_parts(packet.b as *const u8, packet.c) }, packet.uid, packet.gid),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SYS_DUP => self.dup(packet.b),
 | 
					            SYS_DUP => self.dup(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
				
			||||||
            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
					            SYS_READ => self.read(packet.b, unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }),
 | 
				
			||||||
            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
					            SYS_WRITE => self.write(packet.b, unsafe { slice::from_raw_parts(packet.c as *const u8, packet.d) }),
 | 
				
			||||||
            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
					            SYS_LSEEK => self.seek(packet.b, packet.c, packet.d),
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ pub trait SchemeMut {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Resource operations */
 | 
					    /* Resource operations */
 | 
				
			||||||
    #[allow(unused_variables)]
 | 
					    #[allow(unused_variables)]
 | 
				
			||||||
    fn dup(&mut self, old_id: usize) -> Result<usize> {
 | 
					    fn dup(&mut self, old_id: usize, buf: &[u8]) -> Result<usize> {
 | 
				
			||||||
        Err(Error::new(EBADF))
 | 
					        Err(Error::new(EBADF))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue