Add specification to vesad
Fix piping Fix bug where resources are not closed Add arpd Remove question_mark features
This commit is contained in:
		
							parent
							
								
									05a5c52f68
								
							
						
					
					
						commit
						ad448956d6
					
				
					 12 changed files with 360 additions and 93 deletions
				
			
		
							
								
								
									
										1
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -343,6 +343,7 @@ userutils: \
 | 
			
		|||
	filesystem/bin/sudo
 | 
			
		||||
 | 
			
		||||
schemes: \
 | 
			
		||||
	filesystem/bin/arpd \
 | 
			
		||||
	filesystem/bin/ethernetd \
 | 
			
		||||
	filesystem/bin/example \
 | 
			
		||||
	filesystem/bin/ipd \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
#![feature(question_mark)]
 | 
			
		||||
 | 
			
		||||
extern crate syscall;
 | 
			
		||||
 | 
			
		||||
use std::{mem, ptr};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,3 @@
 | 
			
		|||
#![feature(question_mark)]
 | 
			
		||||
 | 
			
		||||
extern crate syscall;
 | 
			
		||||
 | 
			
		||||
pub use resource::Resource;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,14 @@
 | 
			
		|||
#![feature(alloc)]
 | 
			
		||||
#![feature(asm)]
 | 
			
		||||
#![feature(heap_api)]
 | 
			
		||||
#![feature(question_mark)]
 | 
			
		||||
 | 
			
		||||
extern crate alloc;
 | 
			
		||||
extern crate orbclient;
 | 
			
		||||
extern crate syscall;
 | 
			
		||||
 | 
			
		||||
use std::{env, thread};
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{Read, Write};
 | 
			
		||||
use std::thread;
 | 
			
		||||
use syscall::{physmap, physunmap, Packet, Scheme, MAP_WRITE, MAP_WRITE_COMBINE};
 | 
			
		||||
 | 
			
		||||
use mode_info::VBEModeInfo;
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +22,18 @@ pub mod scheme;
 | 
			
		|||
pub mod screen;
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let mut spec = Vec::new();
 | 
			
		||||
 | 
			
		||||
    for arg in env::args().skip(1) {
 | 
			
		||||
        if arg == "T" {
 | 
			
		||||
            spec.push(false);
 | 
			
		||||
        } else if arg == "G" {
 | 
			
		||||
            spec.push(true);
 | 
			
		||||
        } else {
 | 
			
		||||
            println!("vesad: unknown screen type: {}", arg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let width;
 | 
			
		||||
    let height;
 | 
			
		||||
    let physbaseptr;
 | 
			
		||||
| 
						 | 
				
			
			@ -46,7 +57,7 @@ fn main() {
 | 
			
		|||
            let onscreen = unsafe { physmap(physbaseptr, size * 4, MAP_WRITE | MAP_WRITE_COMBINE).expect("vesad: failed to map VBE LFB") };
 | 
			
		||||
            unsafe { fast_set64(onscreen as *mut u64, 0, size/2) };
 | 
			
		||||
 | 
			
		||||
            let scheme = DisplayScheme::new(width, height, onscreen);
 | 
			
		||||
            let scheme = DisplayScheme::new(width, height, onscreen, &spec);
 | 
			
		||||
 | 
			
		||||
            let mut blocked = Vec::new();
 | 
			
		||||
            loop {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,20 +13,30 @@ pub struct DisplayScheme {
 | 
			
		|||
    height: usize,
 | 
			
		||||
    onscreen: usize,
 | 
			
		||||
    active: Cell<usize>,
 | 
			
		||||
    next_screen: Cell<usize>,
 | 
			
		||||
    screens: RefCell<BTreeMap<usize, Box<Screen>>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DisplayScheme {
 | 
			
		||||
    pub fn new(width: usize, height: usize, onscreen: usize) -> DisplayScheme {
 | 
			
		||||
    pub fn new(width: usize, height: usize, onscreen: usize, spec: &[bool]) -> DisplayScheme {
 | 
			
		||||
        let mut screens: BTreeMap<usize, Box<Screen>> = BTreeMap::new();
 | 
			
		||||
        screens.insert(1, Box::new(TextScreen::new(Display::new(width, height, onscreen))));
 | 
			
		||||
        screens.insert(2, Box::new(GraphicScreen::new(Display::new(width, height, onscreen))));
 | 
			
		||||
 | 
			
		||||
        let mut screen_i = 1;
 | 
			
		||||
        for &screen_type in spec.iter() {
 | 
			
		||||
            if screen_type {
 | 
			
		||||
                screens.insert(screen_i, Box::new(GraphicScreen::new(Display::new(width, height, onscreen))));
 | 
			
		||||
            } else {
 | 
			
		||||
                screens.insert(screen_i, Box::new(TextScreen::new(Display::new(width, height, onscreen))));
 | 
			
		||||
            }
 | 
			
		||||
            screen_i += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        DisplayScheme {
 | 
			
		||||
            width: width,
 | 
			
		||||
            height: height,
 | 
			
		||||
            onscreen: onscreen,
 | 
			
		||||
            active: Cell::new(1),
 | 
			
		||||
            next_screen: Cell::new(screen_i),
 | 
			
		||||
            screens: RefCell::new(screens)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,13 @@
 | 
			
		|||
initfs:bin/pcid initfs:etc/pcid.toml
 | 
			
		||||
initfs:bin/redoxfs disk:0
 | 
			
		||||
initfs:bin/pcid file:etc/pcid.toml
 | 
			
		||||
file:bin/vesad
 | 
			
		||||
file:bin/vesad T T G
 | 
			
		||||
file:bin/ps2d
 | 
			
		||||
file:bin/ethernetd
 | 
			
		||||
file:bin/arpd
 | 
			
		||||
file:bin/ipd
 | 
			
		||||
file:bin/tcpd
 | 
			
		||||
file:bin/udpd
 | 
			
		||||
file:bin/getty display:1
 | 
			
		||||
#file:bin/orbital display:2
 | 
			
		||||
file:bin/getty display:2
 | 
			
		||||
#file:bin/orbital display:3
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
use alloc::arc::{Arc, Weak};
 | 
			
		||||
use collections::BTreeMap;
 | 
			
		||||
use collections::{BTreeMap, VecDeque};
 | 
			
		||||
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 | 
			
		||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
 | 
			
		||||
use spin::{Mutex, Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
 | 
			
		||||
 | 
			
		||||
use sync::WaitQueue;
 | 
			
		||||
use sync::WaitCondition;
 | 
			
		||||
use syscall::error::{Error, Result, EBADF, EPIPE};
 | 
			
		||||
use syscall::scheme::Scheme;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +30,8 @@ fn pipes_mut() -> RwLockWriteGuard<'static, (BTreeMap<usize, PipeRead>, BTreeMap
 | 
			
		|||
pub fn pipe(_flags: usize) -> (usize, usize) {
 | 
			
		||||
    let mut pipes = pipes_mut();
 | 
			
		||||
    let read_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
 | 
			
		||||
    let read = PipeRead::new();
 | 
			
		||||
    let write_id = PIPE_NEXT_ID.fetch_add(1, Ordering::SeqCst);
 | 
			
		||||
    let read = PipeRead::new();
 | 
			
		||||
    let write = PipeWrite::new(&read);
 | 
			
		||||
    pipes.0.insert(read_id, read);
 | 
			
		||||
    pipes.1.insert(write_id, write);
 | 
			
		||||
| 
						 | 
				
			
			@ -104,21 +104,43 @@ impl Scheme for PipeScheme {
 | 
			
		|||
/// Read side of a pipe
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct PipeRead {
 | 
			
		||||
    vec: Arc<WaitQueue<u8>>
 | 
			
		||||
    condition: Arc<WaitCondition>,
 | 
			
		||||
    vec: Arc<Mutex<VecDeque<u8>>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PipeRead {
 | 
			
		||||
    pub fn new() -> Self {
 | 
			
		||||
        PipeRead {
 | 
			
		||||
            vec: Arc::new(WaitQueue::new())
 | 
			
		||||
            condition: Arc::new(WaitCondition::new()),
 | 
			
		||||
            vec: Arc::new(Mutex::new(VecDeque::new())),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn read(&self, buf: &mut [u8]) -> Result<usize> {
 | 
			
		||||
        if buf.is_empty() || (Arc::weak_count(&self.vec) == 0 && self.vec.is_empty()) {
 | 
			
		||||
            Ok(0)
 | 
			
		||||
        } else {
 | 
			
		||||
            Ok(self.vec.receive_into(buf))
 | 
			
		||||
        loop {
 | 
			
		||||
            {
 | 
			
		||||
                let mut vec = self.vec.lock();
 | 
			
		||||
 | 
			
		||||
                let mut i = 0;
 | 
			
		||||
                while i < buf.len() {
 | 
			
		||||
                    if let Some(b) = vec.pop_front() {
 | 
			
		||||
                        buf[i] = b;
 | 
			
		||||
                        i += 1;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if i > 0 {
 | 
			
		||||
                    return Ok(i);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if Arc::weak_count(&self.vec) == 0 {
 | 
			
		||||
                return Ok(0);
 | 
			
		||||
            } else {
 | 
			
		||||
                self.condition.wait();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -126,24 +148,37 @@ impl PipeRead {
 | 
			
		|||
/// Read side of a pipe
 | 
			
		||||
#[derive(Clone)]
 | 
			
		||||
pub struct PipeWrite {
 | 
			
		||||
    vec: Weak<WaitQueue<u8>>,
 | 
			
		||||
    condition: Arc<WaitCondition>,
 | 
			
		||||
    vec: Weak<Mutex<VecDeque<u8>>>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PipeWrite {
 | 
			
		||||
    pub fn new(read: &PipeRead) -> Self {
 | 
			
		||||
        PipeWrite {
 | 
			
		||||
            condition: read.condition.clone(),
 | 
			
		||||
            vec: Arc::downgrade(&read.vec),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn write(&self, buf: &[u8]) -> Result<usize> {
 | 
			
		||||
        match self.vec.upgrade() {
 | 
			
		||||
            Some(vec) => {
 | 
			
		||||
                vec.send_from(buf);
 | 
			
		||||
        if let Some(vec_lock) = self.vec.upgrade() {
 | 
			
		||||
            let mut vec = vec_lock.lock();
 | 
			
		||||
 | 
			
		||||
                Ok(buf.len())
 | 
			
		||||
            },
 | 
			
		||||
            None => Err(Error::new(EPIPE))
 | 
			
		||||
            for &b in buf.iter() {
 | 
			
		||||
                vec.push_back(b);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            self.condition.notify();
 | 
			
		||||
 | 
			
		||||
            Ok(buf.len())
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(Error::new(EPIPE))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Drop for PipeWrite {
 | 
			
		||||
    fn drop(&mut self) {
 | 
			
		||||
        self.condition.notify();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,7 @@ use alloc::boxed::Box;
 | 
			
		|||
use collections::{BTreeMap, Vec};
 | 
			
		||||
use core::{mem, str};
 | 
			
		||||
use core::ops::DerefMut;
 | 
			
		||||
use spin::{Mutex, RwLock};
 | 
			
		||||
use spin::Mutex;
 | 
			
		||||
 | 
			
		||||
use arch;
 | 
			
		||||
use arch::externs::memcpy;
 | 
			
		||||
| 
						 | 
				
			
			@ -596,26 +596,56 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
 | 
			
		|||
    unsafe { usermode(entry, sp); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn terminate(context_lock: Arc<RwLock<context::Context>>, status: usize) {
 | 
			
		||||
    let mut close_files = Vec::new();
 | 
			
		||||
pub fn exit(status: usize) -> ! {
 | 
			
		||||
    {
 | 
			
		||||
        let (vfork, ppid) = {
 | 
			
		||||
        let context_lock = {
 | 
			
		||||
            let contexts = context::contexts();
 | 
			
		||||
            let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exit failed to find context");
 | 
			
		||||
            context_lock.clone()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let mut close_files = Vec::new();
 | 
			
		||||
        {
 | 
			
		||||
            let mut context = context_lock.write();
 | 
			
		||||
            context.image.clear();
 | 
			
		||||
            drop(context.heap.take());
 | 
			
		||||
            drop(context.stack.take());
 | 
			
		||||
            context.grants = Arc::new(Mutex::new(Vec::new()));
 | 
			
		||||
            if Arc::strong_count(&context.files) == 1 {
 | 
			
		||||
                mem::swap(context.files.lock().deref_mut(), &mut close_files);
 | 
			
		||||
            }
 | 
			
		||||
            context.files = Arc::new(Mutex::new(Vec::new()));
 | 
			
		||||
            context.status = context::Status::Exited(status);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// Files must be closed while context is valid so that messages can be passed
 | 
			
		||||
        for (fd, file_option) in close_files.drain(..).enumerate() {
 | 
			
		||||
            if let Some(file) = file_option {
 | 
			
		||||
                context::event::unregister(fd, file.scheme, file.number);
 | 
			
		||||
 | 
			
		||||
                let scheme_option = {
 | 
			
		||||
                    let schemes = scheme::schemes();
 | 
			
		||||
                    schemes.get(file.scheme).map(|scheme| scheme.clone())
 | 
			
		||||
                };
 | 
			
		||||
                if let Some(scheme) = scheme_option {
 | 
			
		||||
                    let _ = scheme.close(file.number);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let (vfork, ppid) = {
 | 
			
		||||
            let mut context = context_lock.write();
 | 
			
		||||
 | 
			
		||||
            context.image.clear();
 | 
			
		||||
            drop(context.heap.take());
 | 
			
		||||
            drop(context.stack.take());
 | 
			
		||||
            context.grants = Arc::new(Mutex::new(Vec::new()));
 | 
			
		||||
 | 
			
		||||
            let vfork = context.vfork;
 | 
			
		||||
            context.vfork = false;
 | 
			
		||||
 | 
			
		||||
            context.status = context::Status::Exited(status);
 | 
			
		||||
 | 
			
		||||
            context.waitpid.notify();
 | 
			
		||||
 | 
			
		||||
            (vfork, context.ppid)
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if vfork {
 | 
			
		||||
            let contexts = context::contexts();
 | 
			
		||||
            if let Some(parent_lock) = contexts.get(ppid) {
 | 
			
		||||
| 
						 | 
				
			
			@ -629,31 +659,6 @@ fn terminate(context_lock: Arc<RwLock<context::Context>>, status: usize) {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (fd, file_option) in close_files.drain(..).enumerate() {
 | 
			
		||||
        if let Some(file) = file_option {
 | 
			
		||||
            context::event::unregister(fd, file.scheme, file.number);
 | 
			
		||||
 | 
			
		||||
            let scheme_option = {
 | 
			
		||||
                let schemes = scheme::schemes();
 | 
			
		||||
                schemes.get(file.scheme).map(|scheme| scheme.clone())
 | 
			
		||||
            };
 | 
			
		||||
            if let Some(scheme) = scheme_option {
 | 
			
		||||
                let _ = scheme.close(file.number);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn exit(status: usize) -> ! {
 | 
			
		||||
    {
 | 
			
		||||
        let context_lock = {
 | 
			
		||||
            let contexts = context::contexts();
 | 
			
		||||
            let context_lock = contexts.current().ok_or(Error::new(ESRCH)).expect("exit failed to find context");
 | 
			
		||||
            context_lock.clone()
 | 
			
		||||
        };
 | 
			
		||||
        terminate(context_lock, status);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsafe { context::switch(); }
 | 
			
		||||
 | 
			
		||||
    unreachable!();
 | 
			
		||||
| 
						 | 
				
			
			@ -702,45 +707,45 @@ pub fn iopl(_level: usize) -> Result<usize> {
 | 
			
		|||
pub fn kill(pid: usize, sig: usize) -> Result<usize> {
 | 
			
		||||
    use syscall::flag::*;
 | 
			
		||||
 | 
			
		||||
    let context_lock = {
 | 
			
		||||
    let _context_lock = {
 | 
			
		||||
        let contexts = context::contexts();
 | 
			
		||||
        let context_lock = contexts.get(pid).ok_or(Error::new(ESRCH))?;
 | 
			
		||||
        context_lock.clone()
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let term = |context_lock| {
 | 
			
		||||
        terminate(context_lock, !sig);
 | 
			
		||||
    let term = || {
 | 
			
		||||
        println!("Terminate {}", pid);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let core = |context_lock| {
 | 
			
		||||
        terminate(context_lock, !sig);
 | 
			
		||||
    let core = || {
 | 
			
		||||
        println!("Core {}", pid);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let stop = || {
 | 
			
		||||
 | 
			
		||||
        println!("Stop {}", pid);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let cont = || {
 | 
			
		||||
 | 
			
		||||
        println!("Continue {}", pid);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    match sig {
 | 
			
		||||
        0 => (),
 | 
			
		||||
        SIGHUP => term(context_lock),
 | 
			
		||||
        SIGINT => term(context_lock),
 | 
			
		||||
        SIGQUIT => core(context_lock),
 | 
			
		||||
        SIGILL => core(context_lock),
 | 
			
		||||
        SIGTRAP => core(context_lock),
 | 
			
		||||
        SIGABRT => core(context_lock),
 | 
			
		||||
        SIGBUS => core(context_lock),
 | 
			
		||||
        SIGFPE => core(context_lock),
 | 
			
		||||
        SIGKILL => term(context_lock),
 | 
			
		||||
        SIGUSR1 => term(context_lock),
 | 
			
		||||
        SIGSEGV => core(context_lock),
 | 
			
		||||
        SIGPIPE => term(context_lock),
 | 
			
		||||
        SIGALRM => term(context_lock),
 | 
			
		||||
        SIGTERM => term(context_lock),
 | 
			
		||||
        SIGSTKFLT => term(context_lock),
 | 
			
		||||
        SIGHUP => term(),
 | 
			
		||||
        SIGINT => term(),
 | 
			
		||||
        SIGQUIT => core(),
 | 
			
		||||
        SIGILL => core(),
 | 
			
		||||
        SIGTRAP => core(),
 | 
			
		||||
        SIGABRT => core(),
 | 
			
		||||
        SIGBUS => core(),
 | 
			
		||||
        SIGFPE => core(),
 | 
			
		||||
        SIGKILL => term(),
 | 
			
		||||
        SIGUSR1 => term(),
 | 
			
		||||
        SIGSEGV => core(),
 | 
			
		||||
        SIGPIPE => term(),
 | 
			
		||||
        SIGALRM => term(),
 | 
			
		||||
        SIGTERM => term(),
 | 
			
		||||
        SIGSTKFLT => term(),
 | 
			
		||||
        SIGCHLD => (),
 | 
			
		||||
        SIGCONT => cont(),
 | 
			
		||||
        SIGSTOP => stop(),
 | 
			
		||||
| 
						 | 
				
			
			@ -748,14 +753,14 @@ pub fn kill(pid: usize, sig: usize) -> Result<usize> {
 | 
			
		|||
        SIGTTIN => stop(),
 | 
			
		||||
        SIGTTOU => stop(),
 | 
			
		||||
        SIGURG => (),
 | 
			
		||||
        SIGXCPU => core(context_lock),
 | 
			
		||||
        SIGXFSZ => core(context_lock),
 | 
			
		||||
        SIGVTALRM => term(context_lock),
 | 
			
		||||
        SIGPROF => term(context_lock),
 | 
			
		||||
        SIGXCPU => core(),
 | 
			
		||||
        SIGXFSZ => core(),
 | 
			
		||||
        SIGVTALRM => term(),
 | 
			
		||||
        SIGPROF => term(),
 | 
			
		||||
        SIGWINCH => (),
 | 
			
		||||
        SIGIO => term(context_lock),
 | 
			
		||||
        SIGPWR => term(context_lock),
 | 
			
		||||
        SIGSYS => core(context_lock),
 | 
			
		||||
        SIGIO => term(),
 | 
			
		||||
        SIGPWR => term(),
 | 
			
		||||
        SIGSYS => core(),
 | 
			
		||||
        _ => return Err(Error::new(EINVAL))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1 @@
 | 
			
		|||
Subproject commit 17896532dc139fcc42237effbb7e90cf5bb95702
 | 
			
		||||
Subproject commit b556eefe6071700905abef862967a316dc5b65c7
 | 
			
		||||
							
								
								
									
										6
									
								
								schemes/arpd/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								schemes/arpd/Cargo.toml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
[package]
 | 
			
		||||
name = "arpd"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
syscall = { path = "../../syscall/" }
 | 
			
		||||
							
								
								
									
										163
									
								
								schemes/arpd/src/common.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								schemes/arpd/src/common.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,163 @@
 | 
			
		|||
use std::{mem, slice, u8, u16};
 | 
			
		||||
 | 
			
		||||
pub static mut MAC_ADDR: MacAddr = MacAddr { bytes: [0x50, 0x51, 0x52, 0x53, 0x54, 0x55] };
 | 
			
		||||
 | 
			
		||||
pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] };
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone)]
 | 
			
		||||
#[allow(non_camel_case_types)]
 | 
			
		||||
#[repr(packed)]
 | 
			
		||||
pub struct n16(u16);
 | 
			
		||||
 | 
			
		||||
impl n16 {
 | 
			
		||||
    pub fn new(value: u16) -> Self {
 | 
			
		||||
        n16(value.to_be())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get(&self) -> u16 {
 | 
			
		||||
        u16::from_be(self.0)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn set(&mut self, value: u16) {
 | 
			
		||||
        self.0 = value.to_be();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone)]
 | 
			
		||||
pub struct MacAddr {
 | 
			
		||||
    pub bytes: [u8; 6],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MacAddr {
 | 
			
		||||
    pub fn equals(&self, other: Self) -> bool {
 | 
			
		||||
        for i in 0..6 {
 | 
			
		||||
            if self.bytes[i] != other.bytes[i] {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn from_str(string: &str) -> Self {
 | 
			
		||||
        let mut addr = MacAddr { bytes: [0, 0, 0, 0, 0, 0] };
 | 
			
		||||
 | 
			
		||||
        let mut i = 0;
 | 
			
		||||
        for part in string.split('.') {
 | 
			
		||||
            let octet = u8::from_str_radix(part, 16).unwrap_or(0);
 | 
			
		||||
            match i {
 | 
			
		||||
                0 => addr.bytes[0] = octet,
 | 
			
		||||
                1 => addr.bytes[1] = octet,
 | 
			
		||||
                2 => addr.bytes[2] = octet,
 | 
			
		||||
                3 => addr.bytes[3] = octet,
 | 
			
		||||
                4 => addr.bytes[4] = octet,
 | 
			
		||||
                5 => addr.bytes[5] = octet,
 | 
			
		||||
                _ => break,
 | 
			
		||||
            }
 | 
			
		||||
            i += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_string(&self) -> String {
 | 
			
		||||
        let mut string = String::new();
 | 
			
		||||
        for i in 0..6 {
 | 
			
		||||
            if i > 0 {
 | 
			
		||||
                string.push('.');
 | 
			
		||||
            }
 | 
			
		||||
            string.push_str(&format!("{:X}", self.bytes[i]));
 | 
			
		||||
        }
 | 
			
		||||
        string
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone)]
 | 
			
		||||
pub struct Ipv4Addr {
 | 
			
		||||
    pub bytes: [u8; 4],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ipv4Addr {
 | 
			
		||||
    pub fn equals(&self, other: Self) -> bool {
 | 
			
		||||
        for i in 0..4 {
 | 
			
		||||
            if self.bytes[i] != other.bytes[i] {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn from_str(string: &str) -> Self {
 | 
			
		||||
        let mut addr = Ipv4Addr { bytes: [0, 0, 0, 0] };
 | 
			
		||||
 | 
			
		||||
        let mut i = 0;
 | 
			
		||||
        for part in string.split('.') {
 | 
			
		||||
            let octet = part.parse::<u8>().unwrap_or(0);
 | 
			
		||||
            match i {
 | 
			
		||||
                0 => addr.bytes[0] = octet,
 | 
			
		||||
                1 => addr.bytes[1] = octet,
 | 
			
		||||
                2 => addr.bytes[2] = octet,
 | 
			
		||||
                3 => addr.bytes[3] = octet,
 | 
			
		||||
                _ => break,
 | 
			
		||||
            }
 | 
			
		||||
            i += 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        addr
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_string(&self) -> String {
 | 
			
		||||
        let mut string = String::new();
 | 
			
		||||
 | 
			
		||||
        for i in 0..4 {
 | 
			
		||||
            if i > 0 {
 | 
			
		||||
                string = string + ".";
 | 
			
		||||
            }
 | 
			
		||||
            string = string + &format!("{}", self.bytes[i]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        string
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone)]
 | 
			
		||||
#[repr(packed)]
 | 
			
		||||
pub struct ArpHeader {
 | 
			
		||||
    pub htype: n16,
 | 
			
		||||
    pub ptype: n16,
 | 
			
		||||
    pub hlen: u8,
 | 
			
		||||
    pub plen: u8,
 | 
			
		||||
    pub oper: n16,
 | 
			
		||||
    pub src_mac: MacAddr,
 | 
			
		||||
    pub src_ip: Ipv4Addr,
 | 
			
		||||
    pub dst_mac: MacAddr,
 | 
			
		||||
    pub dst_ip: Ipv4Addr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Arp {
 | 
			
		||||
    pub header: ArpHeader,
 | 
			
		||||
    pub data: Vec<u8>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Arp {
 | 
			
		||||
    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
 | 
			
		||||
        if bytes.len() >= mem::size_of::<ArpHeader>() {
 | 
			
		||||
            unsafe {
 | 
			
		||||
                return Some(Arp {
 | 
			
		||||
                    header: *(bytes.as_ptr() as *const ArpHeader),
 | 
			
		||||
                    data: bytes[mem::size_of::<ArpHeader>() ..].to_vec(),
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        None
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn to_bytes(&self) -> Vec<u8> {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            let header_ptr: *const ArpHeader = &self.header;
 | 
			
		||||
            let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
 | 
			
		||||
                                                          mem::size_of::<ArpHeader>()));
 | 
			
		||||
            ret.extend_from_slice(&self.data);
 | 
			
		||||
            ret
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								schemes/arpd/src/main.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								schemes/arpd/src/main.rs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
extern crate syscall;
 | 
			
		||||
 | 
			
		||||
use std::thread;
 | 
			
		||||
 | 
			
		||||
use common::{MAC_ADDR, IP_ADDR, Arp};
 | 
			
		||||
 | 
			
		||||
pub mod common;
 | 
			
		||||
 | 
			
		||||
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]) {
 | 
			
		||||
                        if packet.header.oper.get() == 1 && packet.header.dst_ip.equals(unsafe { 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 = unsafe { MAC_ADDR };
 | 
			
		||||
                            response.header.src_ip = unsafe { IP_ADDR };
 | 
			
		||||
 | 
			
		||||
                            let _ = syscall::write(link, &response.to_bytes());
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            let _ = syscall::close(link);
 | 
			
		||||
        }
 | 
			
		||||
        panic!("ARP: Failed to open ethernet");
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue