From 67440cf83519ac45b8e14447430a66d290e5a6c1 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 22 Nov 2016 21:00:53 -0700 Subject: [PATCH] Add loopback interface - significant cleanup of ipd --- schemes/ipd/src/interface/ethernet.rs | 151 ++++++++++++++++++ schemes/ipd/src/interface/loopback.rs | 44 ++++++ schemes/ipd/src/interface/mod.rs | 15 ++ schemes/ipd/src/main.rs | 211 +++++++------------------- 4 files changed, 262 insertions(+), 159 deletions(-) create mode 100644 schemes/ipd/src/interface/ethernet.rs create mode 100644 schemes/ipd/src/interface/loopback.rs create mode 100644 schemes/ipd/src/interface/mod.rs diff --git a/schemes/ipd/src/interface/ethernet.rs b/schemes/ipd/src/interface/ethernet.rs new file mode 100644 index 0000000..4c0bb78 --- /dev/null +++ b/schemes/ipd/src/interface/ethernet.rs @@ -0,0 +1,151 @@ +use netutils::{getcfg, n16, Ipv4Addr, MacAddr, Ipv4, EthernetII, EthernetIIHeader, Arp}; +use std::collections::BTreeMap; +use std::fs::File; +use std::io::{Result, Read, Write}; +use std::os::unix::io::FromRawFd; + +use interface::Interface; + +pub struct EthernetInterface { + mac: MacAddr, + ip: Ipv4Addr, + router: Ipv4Addr, + subnet: Ipv4Addr, + arp_file: File, + ip_file: File, + arp: BTreeMap, + rarp: BTreeMap, +} + +impl EthernetInterface { + pub fn new(arp_fd: usize, ip_fd: usize) -> Self { + EthernetInterface { + 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(), + } + } +} + +impl Interface for EthernetInterface { + fn ip(&self) -> Ipv4Addr { + self.ip + } + + fn arp_event(&mut self) -> Result<()> { + loop { + let mut bytes = [0; 65536]; + let count = self.arp_file.read(&mut bytes)?; + if count == 0 { + break; + } + if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { + if let Some(packet) = Arp::from_bytes(&frame.data) { + if packet.header.oper.get() == 1 { + if packet.header.dst_ip == self.ip { + if packet.header.src_ip != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { + self.arp.insert(packet.header.src_ip, frame.header.src); + self.rarp.insert(frame.header.src, packet.header.src_ip); + } + + let mut response = Arp { + header: packet.header, + data: packet.data.clone(), + }; + response.header.oper.set(2); + response.header.dst_mac = packet.header.src_mac; + response.header.dst_ip = packet.header.src_ip; + response.header.src_mac = self.mac; + response.header.src_ip = self.ip; + + let mut response_frame = EthernetII { + header: frame.header, + data: response.to_bytes() + }; + + response_frame.header.dst = response_frame.header.src; + response_frame.header.src = self.mac; + + self.arp_file.write(&response_frame.to_bytes())?; + } + } + } + } + } + + Ok(()) + } + + fn recv(&mut self) -> Result> { + let mut ips = Vec::new(); + + loop { + let mut bytes = [0; 65536]; + let count = self.ip_file.read(&mut bytes)?; + if count == 0 { + break; + } + if let Some(frame) = EthernetII::from_bytes(&bytes[.. count]) { + if let Some(ip) = Ipv4::from_bytes(&frame.data) { + if ip.header.dst == self.ip || ip.header.dst == Ipv4Addr::BROADCAST { + //TODO: Handle ping here + + if ip.header.src != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { + self.arp.insert(ip.header.src, frame.header.src); + self.rarp.insert(frame.header.src, ip.header.src); + } + + ips.push(ip); + } + } + } + } + + Ok(ips) + } + + fn send(&mut self, ip: Ipv4) -> Result { + let mut dst = MacAddr::BROADCAST; + if ip.header.dst != Ipv4Addr::BROADCAST { + let mut needs_routing = false; + + for octet in 0..4 { + let me = self.ip.bytes[octet]; + let mask = self.subnet.bytes[octet]; + let them = ip.header.dst.bytes[octet]; + if me & mask != them & mask { + needs_routing = true; + break; + } + } + + let route_addr = if needs_routing { + self.router + } else { + ip.header.dst + }; + + if let Some(mac) = self.arp.get(&route_addr) { + dst = *mac; + } else { + println!("ipd: need to arp {}", route_addr.to_string()); + } + } + + let frame = EthernetII { + header: EthernetIIHeader { + dst: dst, + src: self.mac, + ethertype: n16::new(0x800), + }, + data: ip.to_bytes() + }; + + self.ip_file.write(&frame.to_bytes()) + } +} diff --git a/schemes/ipd/src/interface/loopback.rs b/schemes/ipd/src/interface/loopback.rs new file mode 100644 index 0000000..842e96a --- /dev/null +++ b/schemes/ipd/src/interface/loopback.rs @@ -0,0 +1,44 @@ +use netutils::{Ipv4Addr, Ipv4}; +use std::io::Result; + +use interface::Interface; + +pub struct LoopbackInterface { + ip: Ipv4Addr, + packets: Vec +} + +impl LoopbackInterface { + pub fn new() -> Self { + LoopbackInterface { + ip: Ipv4Addr::LOOPBACK, + packets: Vec::new() + } + } +} + +impl Interface for LoopbackInterface { + fn ip(&self) -> Ipv4Addr { + self.ip + } + + fn arp_event(&mut self) -> Result<()> { + Ok(()) + } + + fn recv(&mut self) -> Result> { + let mut ips = Vec::new(); + + for ip in self.packets.drain(..) { + ips.push(ip); + } + + Ok(ips) + } + + fn send(&mut self, ip: Ipv4) -> Result { + self.packets.push(ip); + + Ok(0) + } +} diff --git a/schemes/ipd/src/interface/mod.rs b/schemes/ipd/src/interface/mod.rs new file mode 100644 index 0000000..36458dc --- /dev/null +++ b/schemes/ipd/src/interface/mod.rs @@ -0,0 +1,15 @@ +use netutils::{Ipv4, Ipv4Addr}; +use std::io::Result; + +pub use self::ethernet::EthernetInterface; +pub use self::loopback::LoopbackInterface; + +mod ethernet; +mod loopback; + +pub trait Interface { + fn ip(&self) -> Ipv4Addr; + fn arp_event(&mut self) -> Result<()>; + fn recv(&mut self) -> Result>; + fn send(&mut self, ip: Ipv4) -> Result; +} diff --git a/schemes/ipd/src/main.rs b/schemes/ipd/src/main.rs index 6f3735d..a9cd024 100644 --- a/schemes/ipd/src/main.rs +++ b/schemes/ipd/src/main.rs @@ -3,7 +3,7 @@ extern crate netutils; extern crate syscall; use event::EventQueue; -use netutils::{getcfg, n16, Ipv4Addr, MacAddr, Ipv4, EthernetII, EthernetIIHeader, Arp, Tcp}; +use netutils::{Ipv4Addr, Ipv4, Tcp}; use std::cell::RefCell; use std::collections::{BTreeMap, VecDeque}; use std::fs::File; @@ -16,31 +16,9 @@ use syscall::error::{Error, Result, EACCES, EADDRNOTAVAIL, EBADF, EIO, EINVAL, E use syscall::flag::{EVENT_READ, O_NONBLOCK}; use syscall::scheme::SchemeMut; -struct Interface { - mac: MacAddr, - ip: Ipv4Addr, - router: Ipv4Addr, - subnet: Ipv4Addr, - arp_file: File, - ip_file: File, - arp: BTreeMap, - rarp: BTreeMap, -} +use interface::{Interface, EthernetInterface, LoopbackInterface}; -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 interface; struct Handle { proto: u8, @@ -52,7 +30,7 @@ struct Handle { struct Ipd { scheme_file: File, - interfaces: Vec, + interfaces: Vec>, next_id: usize, handles: BTreeMap, } @@ -89,103 +67,40 @@ impl Ipd { 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 { - if packet.header.src_ip != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - interface.arp.insert(packet.header.src_ip, frame.header.src); - interface.rarp.insert(frame.header.src, packet.header.src_ip); - } - - let mut response = Arp { - header: packet.header, - data: packet.data.clone(), - }; - response.header.oper.set(2); - response.header.dst_mac = packet.header.src_mac; - response.header.dst_ip = packet.header.src_ip; - response.header.src_mac = 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 { - if ip.header.src != Ipv4Addr::BROADCAST && frame.header.src != MacAddr::BROADCAST { - interface.arp.insert(ip.header.src, frame.header.src); - interface.rarp.insert(frame.header.src, ip.header.src); + for ip in interface.recv()? { + for (id, handle) in self.handles.iter_mut() { + if ip.header.proto == handle.proto { + handle.data.push_back(ip.to_bytes()); + + while ! handle.todo.is_empty() && ! handle.data.is_empty() { + let mut packet = handle.todo.pop_front().unwrap(); + let buf = unsafe { slice::from_raw_parts_mut(packet.c as *mut u8, packet.d) }; + let data = handle.data.pop_front().unwrap(); + + let mut i = 0; + while i < buf.len() && i < data.len() { + buf[i] = data[i]; + i += 1; } + packet.a = i; - //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()); + self.scheme_file.write(&packet)?; + } - 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() - })?; - } - } - } + 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() + })?; } } } @@ -264,8 +179,9 @@ impl SchemeMut for Ipd { 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; + let if_ip = interface.ip(); + if ip.header.src == if_ip || ip.header.src == Ipv4Addr::NULL { + ip.header.src = if_ip; ip.header.proto = handle.proto; if let Some(mut tcp) = Tcp::from_bytes(&ip.data) { @@ -275,43 +191,7 @@ impl SchemeMut for Ipd { ip.checksum(); - let mut dst = MacAddr::BROADCAST; - if ip.header.dst != Ipv4Addr::BROADCAST { - let mut needs_routing = false; - - for octet in 0..4 { - let me = interface.ip.bytes[octet]; - let mask = interface.subnet.bytes[octet]; - let them = ip.header.dst.bytes[octet]; - if me & mask != them & mask { - needs_routing = true; - break; - } - } - - let route_addr = if needs_routing { - interface.router - } else { - ip.header.dst - }; - - if let Some(mac) = interface.arp.get(&route_addr) { - dst = *mac; - } else { - println!("ipd: need to arp {}", route_addr.to_string()); - } - } - - let frame = EthernetII { - header: EthernetIIHeader { - dst: dst, - src: interface.mac, - ethertype: n16::new(0x800), - }, - data: ip.to_bytes() - }; - - interface.ip_file.write(&frame.to_bytes()).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; + interface.send(ip).map_err(|err| Error::new(err.raw_os_error().unwrap_or(EIO)))?; return Ok(buf.len()); } @@ -371,6 +251,13 @@ fn main() { let mut event_queue = EventQueue::<()>::new().expect("ipd: failed to create event queue"); + let loopback_id = { + let mut ipd = ipd.borrow_mut(); + let if_id = ipd.interfaces.len(); + ipd.interfaces.push(Box::new(LoopbackInterface::new())); + if_id + }; + //TODO: Multiple interfaces { let arp_fd = syscall::open("ethernet:806", syscall::O_RDWR | syscall::O_NONBLOCK).expect("ipd: failed to open ethernet:806"); @@ -378,25 +265,31 @@ fn main() { let if_id = { let mut ipd = ipd.borrow_mut(); let if_id = ipd.interfaces.len(); - ipd.interfaces.push(Interface::new(arp_fd, ip_fd)); + ipd.interfaces.push(Box::new(EthernetInterface::new(arp_fd, ip_fd))); if_id }; let arp_ipd = ipd.clone(); event_queue.add(arp_fd, move |_count: usize| -> io::Result> { - arp_ipd.borrow_mut().arp_event(if_id)?; + if let Some(mut interface) = arp_ipd.borrow_mut().interfaces.get_mut(if_id) { + interface.arp_event()?; + } + Ok(None) }).expect("ipd: failed to listen to events on ethernet:806"); let ip_ipd = ipd.clone(); event_queue.add(ip_fd, move |_count: usize| -> io::Result> { ip_ipd.borrow_mut().ip_event(if_id)?; + Ok(None) }).expect("ipd: failed to listen to events on ethernet:800"); } event_queue.add(scheme_fd, move |_count: usize| -> io::Result> { + ipd.borrow_mut().ip_event(loopback_id)?; ipd.borrow_mut().scheme_event()?; + ipd.borrow_mut().ip_event(loopback_id)?; Ok(None) }).expect("ipd: failed to listen to events on :ip");