This commit is contained in:
Dennis Schwerdel 2015-11-23 00:49:58 +01:00
parent 83f53c16d7
commit 28a79f2d47
5 changed files with 204 additions and 249 deletions

View File

@ -1,44 +1,111 @@
use std::net::{SocketAddr, ToSocketAddrs}; use std::net::{SocketAddr, ToSocketAddrs, Ipv4Addr, Ipv6Addr};
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::Hasher; use std::hash::Hasher;
use std::net::UdpSocket; use std::net::UdpSocket;
use std::io::Read; use std::io::Read;
use std::fmt; use std::{fmt, ptr};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::str::FromStr;
use time::{Duration, SteadyTime, precise_time_ns}; use time::{Duration, SteadyTime, precise_time_ns};
use epoll; use epoll;
use super::device::{TunDevice, TapDevice}; use super::device::{TunDevice, TapDevice};
use super::udpmessage::{encode, decode, Options, Message}; use super::udpmessage::{encode, decode, Options, Message};
use super::ethernet::{Frame, EthAddr, MacTable}; use super::ethernet::{Frame, MacTable};
use super::ip::{InternetProtocol, IpAddress, RoutingTable}; use super::ip::{InternetProtocol, RoutingTable};
use super::util::as_bytes;
pub type NetworkId = u64; pub type NetworkId = u64;
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
pub struct Address(pub Vec<u8>);
impl fmt::Debug for Address {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self.0.len() {
4 => write!(formatter, "{}.{}.{}.{}", self.0[0], self.0[1], self.0[2], self.0[3]),
6 => write!(formatter, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]),
16 => write!(formatter, "{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}:{:x}{:x}",
self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5], self.0[6], self.0[7],
self.0[8], self.0[9], self.0[10], self.0[11], self.0[12], self.0[13], self.0[14], self.0[15]
),
_ => self.0.fmt(formatter)
}
}
}
impl FromStr for Address {
type Err=Error;
fn from_str(text: &str) -> Result<Self, Self::Err> {
if let Ok(addr) = Ipv4Addr::from_str(text) {
let ip = addr.octets();
let mut res = Vec::with_capacity(4);
unsafe {
res.set_len(4);
ptr::copy_nonoverlapping(ip.as_ptr(), res.as_mut_ptr(), ip.len());
}
return Ok(Address(res));
}
if let Ok(addr) = Ipv6Addr::from_str(text) {
let mut segments = addr.segments();
for i in 0..8 {
segments[i] = segments[i].to_be();
}
let bytes = unsafe { as_bytes(&segments) };
let mut res = Vec::with_capacity(16);
unsafe {
res.set_len(16);
ptr::copy_nonoverlapping(bytes.as_ptr(), res.as_mut_ptr(), bytes.len());
}
return Ok(Address(res));
}
//FIXME: implement for mac addresses
return Err(Error::ParseError("Failed to parse address"))
}
}
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
pub struct Range {
pub base: Address,
pub prefix_len: u8
}
impl FromStr for Range {
type Err=Error;
fn from_str(text: &str) -> Result<Self, Self::Err> {
let pos = match text.find("/") {
Some(pos) => pos,
None => return Err(Error::ParseError("Invalid range format"))
};
let prefix_len = try!(u8::from_str(&text[pos+1..])
.map_err(|_| Error::ParseError("Failed to parse prefix length")));
let base = try!(Address::from_str(&text[..pos]));
Ok(Range{base: base, prefix_len: prefix_len})
}
}
#[derive(RustcDecodable, Debug)] #[derive(RustcDecodable, Debug)]
pub enum Behavior { pub enum Behavior {
Normal, Hub, Switch, Router Normal, Hub, Switch, Router
} }
pub trait Address: Sized + fmt::Debug + Clone {
fn from_bytes(&[u8]) -> Result<Self, Error>;
fn to_bytes(&self) -> Vec<u8>;
}
pub trait Table { pub trait Table {
type Address: Address; fn learn(&mut self, Address, Option<u8>, SocketAddr);
fn learn(&mut self, Self::Address, SocketAddr); fn lookup(&self, &Address) -> Option<SocketAddr>;
fn lookup(&self, &Self::Address) -> Option<SocketAddr>;
fn housekeep(&mut self); fn housekeep(&mut self);
fn remove_all(&mut self, SocketAddr); fn remove_all(&mut self, SocketAddr);
} }
pub trait Protocol: Sized { pub trait Protocol: Sized {
type Address: Address; fn parse(&[u8]) -> Result<(Address, Address), Error>;
fn parse(&[u8]) -> Result<(Self::Address, Self::Address), Error>;
} }
pub trait VirtualInterface: AsRawFd { pub trait VirtualInterface: AsRawFd {
@ -124,9 +191,9 @@ impl PeerList {
} }
pub struct GenericCloud<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterface> { pub struct GenericCloud<T: Table, P: Protocol, I: VirtualInterface> {
peers: PeerList, peers: PeerList,
addresses: Vec<A>, addresses: Vec<Range>,
learning: bool, learning: bool,
broadcast: bool, broadcast: bool,
reconnect_peers: Vec<SocketAddr>, reconnect_peers: Vec<SocketAddr>,
@ -138,12 +205,12 @@ pub struct GenericCloud<A: Address, T: Table<Address=A>, M: Protocol<Address=A>,
update_freq: Duration, update_freq: Duration,
buffer_out: [u8; 64*1024], buffer_out: [u8; 64*1024],
next_housekeep: SteadyTime, next_housekeep: SteadyTime,
_dummy_m: PhantomData<M>, _dummy_m: PhantomData<P>,
} }
impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterface> GenericCloud<A, T, M, I> { impl<T: Table, P: Protocol, I: VirtualInterface> GenericCloud<T, P, I> {
pub fn new(device: I, listen: String, network_id: Option<NetworkId>, table: T, pub fn new(device: I, listen: String, network_id: Option<NetworkId>, table: T,
peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<A>) -> Self { peer_timeout: Duration, learning: bool, broadcast: bool, addresses: Vec<Range>) -> Self {
let socket = match UdpSocket::bind(&listen as &str) { let socket = match UdpSocket::bind(&listen as &str) {
Ok(socket) => socket, Ok(socket) => socket,
_ => panic!("Failed to open socket") _ => panic!("Failed to open socket")
@ -166,7 +233,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
} }
} }
fn send_msg<Addr: ToSocketAddrs+fmt::Display>(&mut self, addr: Addr, msg: &Message<A>) -> Result<(), Error> { fn send_msg<Addr: ToSocketAddrs+fmt::Display>(&mut self, addr: Addr, msg: &Message) -> Result<(), Error> {
debug!("Sending {:?} to {}", msg, addr); debug!("Sending {:?} to {}", msg, addr);
let mut options = Options::default(); let mut options = Options::default();
options.network_id = self.network_id; options.network_id = self.network_id;
@ -224,7 +291,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
} }
fn handle_interface_data(&mut self, payload: &[u8]) -> Result<(), Error> { fn handle_interface_data(&mut self, payload: &[u8]) -> Result<(), Error> {
let (src, dst) = try!(M::parse(payload)); let (src, dst) = try!(P::parse(payload));
debug!("Read data from interface: src: {:?}, dst: {:?}, {} bytes", src, dst, payload.len()); debug!("Read data from interface: src: {:?}, dst: {:?}, {} bytes", src, dst, payload.len());
match self.table.lookup(&dst) { match self.table.lookup(&dst) {
Some(addr) => { Some(addr) => {
@ -250,7 +317,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
Ok(()) Ok(())
} }
fn handle_net_message(&mut self, peer: SocketAddr, options: Options, msg: Message<A>) -> Result<(), Error> { fn handle_net_message(&mut self, peer: SocketAddr, options: Options, msg: Message) -> Result<(), Error> {
if let Some(id) = self.network_id { if let Some(id) = self.network_id {
if options.network_id != Some(id) { if options.network_id != Some(id) {
info!("Ignoring message from {} with wrong token {:?}", peer, options.network_id); info!("Ignoring message from {} with wrong token {:?}", peer, options.network_id);
@ -260,7 +327,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
debug!("Recieved {:?} from {}", msg, peer); debug!("Recieved {:?} from {}", msg, peer);
match msg { match msg {
Message::Data(payload) => { Message::Data(payload) => {
let (src, _dst) = try!(M::parse(payload)); let (src, _dst) = try!(P::parse(payload));
debug!("Writing data to device: {} bytes", payload.len()); debug!("Writing data to device: {} bytes", payload.len());
match self.device.write(&payload) { match self.device.write(&payload) {
Ok(()) => (), Ok(()) => (),
@ -271,7 +338,8 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
} }
self.peers.add(&peer); self.peers.add(&peer);
if self.learning { if self.learning {
self.table.learn(src, peer); //learn single address
self.table.learn(src, None, peer);
} }
}, },
Message::Peers(peers) => { Message::Peers(peers) => {
@ -282,7 +350,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
} }
} }
}, },
Message::Init(addrs) => { Message::Init(ranges) => {
if self.peers.contains(&peer) { if self.peers.contains(&peer) {
return Ok(()); return Ok(());
} }
@ -291,8 +359,8 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
let own_addrs = self.addresses.clone(); let own_addrs = self.addresses.clone();
try!(self.send_msg(peer, &Message::Init(own_addrs))); try!(self.send_msg(peer, &Message::Init(own_addrs)));
try!(self.send_msg(peer, &Message::Peers(peers))); try!(self.send_msg(peer, &Message::Peers(peers)));
for addr in addrs { for range in ranges {
self.table.learn(addr, peer.clone()); self.table.learn(range.base, Some(range.prefix_len), peer.clone());
} }
}, },
Message::Close => { Message::Close => {
@ -349,7 +417,7 @@ impl<A: Address, T: Table<Address=A>, M: Protocol<Address=A>, I: VirtualInterfac
} }
pub type TapCloud = GenericCloud<EthAddr, MacTable, Frame, TapDevice>; pub type TapCloud = GenericCloud<MacTable, Frame, TapDevice>;
impl TapCloud { impl TapCloud {
pub fn new_tap_cloud(device: &str, listen: String, behavior: Behavior, network_id: Option<NetworkId>, mac_timeout: Duration, peer_timeout: Duration) -> Self { pub fn new_tap_cloud(device: &str, listen: String, behavior: Behavior, network_id: Option<NetworkId>, mac_timeout: Duration, peer_timeout: Duration) -> Self {
@ -370,19 +438,19 @@ impl TapCloud {
} }
pub type TunCloud = GenericCloud<IpAddress, RoutingTable, InternetProtocol, TunDevice>; pub type TunCloud = GenericCloud<RoutingTable, InternetProtocol, TunDevice>;
impl TunCloud { impl TunCloud {
pub fn new_tun_cloud(device: &str, listen: String, behavior: Behavior, network_id: Option<NetworkId>, subnets: Vec<String>, peer_timeout: Duration) -> Self { pub fn new_tun_cloud(device: &str, listen: String, behavior: Behavior, network_id: Option<NetworkId>, range_strs: Vec<String>, peer_timeout: Duration) -> Self {
let device = match TunDevice::new(device) { let device = match TunDevice::new(device) {
Ok(device) => device, Ok(device) => device,
_ => panic!("Failed to open tun device") _ => panic!("Failed to open tun device")
}; };
info!("Opened tun device {}", device.ifname()); info!("Opened tun device {}", device.ifname());
let table = RoutingTable::new(); let table = RoutingTable::new();
let mut addrs = Vec::with_capacity(subnets.len()); let mut ranges = Vec::with_capacity(range_strs.len());
for s in subnets { for s in range_strs {
addrs.push(IpAddress::from_str(&s).expect("Invalid subnet")); ranges.push(Range::from_str(&s).expect("Invalid subnet"));
} }
let (learning, broadcasting) = match behavior { let (learning, broadcasting) = match behavior {
Behavior::Normal => (false, false), Behavior::Normal => (false, false),
@ -390,6 +458,6 @@ impl TunCloud {
Behavior::Hub => (false, true), Behavior::Hub => (false, true),
Behavior::Router => (false, false) Behavior::Router => (false, false)
}; };
Self::new(device, listen, network_id, table, peer_timeout, learning, broadcasting, addrs) Self::new(device, listen, network_id, table, peer_timeout, learning, broadcasting, ranges)
} }
} }

View File

@ -1,67 +1,52 @@
use std::{mem, fmt}; use std::ptr;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::Write;
use super::cloud::{Error, Table, Protocol, Address}; use super::cloud::{Error, Table, Protocol, Address};
use super::util::as_obj;
use time::{Duration, SteadyTime}; use time::{Duration, SteadyTime};
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Mac(pub [u8; 6]);
impl fmt::Debug for Mac {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(formatter, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5])
}
}
pub type VlanId = u16;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct EthAddr {
pub mac: Mac,
pub vlan: Option<VlanId>
}
impl Address for EthAddr {
fn from_bytes(_bytes: &[u8]) -> Result<Self, Error> {
unimplemented!()
}
fn to_bytes(&self) -> Vec<u8> {
unimplemented!()
}
}
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Frame; pub struct Frame;
impl Protocol for Frame { impl Protocol for Frame {
type Address = EthAddr; fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
fn parse(data: &[u8]) -> Result<(EthAddr, EthAddr), Error> {
if data.len() < 14 { if data.len() < 14 {
return Err(Error::ParseError("Frame is too short")); return Err(Error::ParseError("Frame is too short"));
} }
let mut pos = 0; let mut pos = 0;
let dst = *unsafe { as_obj::<Mac>(&data[pos..]) }; let dst_data = &data[pos..pos+6];
pos += mem::size_of::<Mac>(); pos += 6;
let src = *unsafe { as_obj::<Mac>(&data[pos..]) }; let src_data = &data[pos..pos+6];
pos += mem::size_of::<Mac>(); pos += 6;
let mut vlan = None;
if data[pos] == 0x81 && data[pos+1] == 0x00 { if data[pos] == 0x81 && data[pos+1] == 0x00 {
pos += 2; pos += 2;
if data.len() < pos + 2 { if data.len() < pos + 2 {
return Err(Error::ParseError("Vlan frame is too short")); return Err(Error::ParseError("Vlan frame is too short"));
} }
vlan = Some(u16::from_be(* unsafe { as_obj::<u16>(&data[pos..]) })); let mut src = Vec::with_capacity(8);
let mut dst = Vec::with_capacity(8);
unsafe {
ptr::copy_nonoverlapping(data.as_ptr(), src.as_mut_ptr(), 2);
ptr::copy_nonoverlapping(src_data.as_ptr(), src[2..].as_mut_ptr(), 6);
src.set_len(8);
ptr::copy_nonoverlapping(data.as_ptr(), dst.as_mut_ptr(), 2);
ptr::copy_nonoverlapping(dst_data.as_ptr(), dst[2..].as_mut_ptr(), 6);
dst.set_len(8);
}
Ok((Address(src), Address(dst)))
} else {
let mut src = Vec::with_capacity(6);
let mut dst = Vec::with_capacity(6);
unsafe {
ptr::copy_nonoverlapping(src_data.as_ptr(), src.as_mut_ptr(), 6);
src.set_len(6);
ptr::copy_nonoverlapping(dst_data.as_ptr(), dst.as_mut_ptr(), 6);
dst.set_len(6);
}
Ok((Address(src), Address(dst)))
} }
Ok((EthAddr{mac: src, vlan: vlan}, EthAddr{mac: dst, vlan: vlan}))
} }
} }
@ -73,7 +58,7 @@ struct MacTableValue {
pub struct MacTable { pub struct MacTable {
table: HashMap<EthAddr, MacTableValue>, table: HashMap<Address, MacTableValue>,
timeout: Duration timeout: Duration
} }
@ -84,30 +69,28 @@ impl MacTable {
} }
impl Table for MacTable { impl Table for MacTable {
type Address = EthAddr;
fn housekeep(&mut self) { fn housekeep(&mut self) {
let now = SteadyTime::now(); let now = SteadyTime::now();
let mut del: Vec<Self::Address> = Vec::new(); let mut del: Vec<Address> = Vec::new();
for (&key, val) in &self.table { for (key, val) in &self.table {
if val.timeout < now { if val.timeout < now {
del.push(key); del.push(key.clone());
} }
} }
for key in del { for key in del {
info!("Forgot mac: {:?} (vlan {:?})", key.mac, key.vlan); info!("Forgot address {:?}", key);
self.table.remove(&key); self.table.remove(&key);
} }
} }
fn learn(&mut self, key: Self::Address, addr: SocketAddr) { fn learn(&mut self, key: Address, _prefix_len: Option<u8>, addr: SocketAddr) {
let value = MacTableValue{address: addr, timeout: SteadyTime::now()+self.timeout}; let value = MacTableValue{address: addr, timeout: SteadyTime::now()+self.timeout};
if self.table.insert(key, value).is_none() { if self.table.insert(key.clone(), value).is_none() {
info!("Learned mac: {:?} (vlan {:?}) => {}", key.mac, key.vlan, addr); info!("Learned address {:?} => {}", key, addr);
} }
} }
fn lookup(&self, key: &Self::Address) -> Option<SocketAddr> { fn lookup(&self, key: &Address) -> Option<SocketAddr> {
match self.table.get(key) { match self.table.get(key) {
Some(value) => Some(value.address), Some(value) => Some(value.address),
None => None None => None
@ -124,14 +107,14 @@ impl Table for MacTable {
fn without_vlan() { fn without_vlan() {
let data = [6,5,4,3,2,1,1,2,3,4,5,6,1,2,3,4,5,6,7,8]; let data = [6,5,4,3,2,1,1,2,3,4,5,6,1,2,3,4,5,6,7,8];
let (src, dst) = Frame::parse(&data).unwrap(); let (src, dst) = Frame::parse(&data).unwrap();
assert_eq!(src, EthAddr{mac: Mac([1,2,3,4,5,6]), vlan: None}); assert_eq!(src, Address(vec![1,2,3,4,5,6]));
assert_eq!(dst, EthAddr{mac: Mac([6,5,4,3,2,1]), vlan: None}); assert_eq!(dst, Address(vec![6,5,4,3,2,1]));
} }
#[test] #[test]
fn with_vlan() { fn with_vlan() {
let data = [6,5,4,3,2,1,1,2,3,4,5,6,0x81,0,4,210,1,2,3,4,5,6,7,8]; let data = [6,5,4,3,2,1,1,2,3,4,5,6,0x81,0,4,210,1,2,3,4,5,6,7,8];
let (src, dst) = Frame::parse(&data).unwrap(); let (src, dst) = Frame::parse(&data).unwrap();
assert_eq!(src, EthAddr{mac: Mac([1,2,3,4,5,6]), vlan: Some(1234)}); assert_eq!(src, Address(vec![4,210,1,2,3,4,5,6]));
assert_eq!(dst, EthAddr{mac: Mac([6,5,4,3,2,1]), vlan: Some(1234)}); assert_eq!(dst, Address(vec![4,210,6,5,4,3,2,1]));
} }

153
src/ip.rs
View File

@ -1,110 +1,15 @@
use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr}; use std::net::SocketAddr;
use std::collections::{hash_map, HashMap}; use std::collections::{hash_map, HashMap};
use std::ptr;
use std::io::Read; use std::io::Read;
use std::str::FromStr;
use super::cloud::{Protocol, Error, Table, Address}; use super::cloud::{Protocol, Error, Table, Address};
use super::util::{as_obj, as_bytes}; use super::util::to_vec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IpAddress {
V4(Ipv4Addr),
V6(Ipv6Addr),
V4Net(Ipv4Addr, u8),
V6Net(Ipv6Addr, u8),
}
impl Address for IpAddress {
fn to_bytes(&self) -> Vec<u8> {
match self {
&IpAddress::V4(addr) => {
let ip = addr.octets();
let mut res = Vec::with_capacity(4);
unsafe {
res.set_len(4);
ptr::copy_nonoverlapping(ip.as_ptr(), res.as_mut_ptr(), ip.len());
}
res
},
&IpAddress::V4Net(addr, prefix_len) => {
let mut bytes = IpAddress::V4(addr).to_bytes();
bytes.push(prefix_len);
bytes
},
&IpAddress::V6(addr) => {
let mut segments = addr.segments();
for i in 0..8 {
segments[i] = segments[i].to_be();
}
let bytes = unsafe { as_bytes(&segments) };
let mut res = Vec::with_capacity(16);
unsafe {
res.set_len(16);
ptr::copy_nonoverlapping(bytes.as_ptr(), res.as_mut_ptr(), bytes.len());
}
res
},
&IpAddress::V6Net(addr, prefix_len) => {
let mut bytes = IpAddress::V6(addr).to_bytes();
bytes.push(prefix_len);
bytes
}
}
}
fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
match bytes.len() {
4 => Ok(IpAddress::V4(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]))),
5 => Ok(IpAddress::V4Net(Ipv4Addr::new(bytes[0], bytes[1], bytes[2], bytes[3]), bytes[4])),
16 => {
let data = unsafe { as_obj::<[u16; 8]>(&bytes) };
Ok(IpAddress::V6(Ipv6Addr::new(
u16::from_be(data[0]), u16::from_be(data[1]),
u16::from_be(data[2]), u16::from_be(data[3]),
u16::from_be(data[4]), u16::from_be(data[5]),
u16::from_be(data[6]), u16::from_be(data[7]),
)))
},
17 => {
let data = unsafe { as_obj::<[u16; 8]>(&bytes) };
Ok(IpAddress::V6Net(Ipv6Addr::new(
u16::from_be(data[0]), u16::from_be(data[1]),
u16::from_be(data[2]), u16::from_be(data[3]),
u16::from_be(data[4]), u16::from_be(data[5]),
u16::from_be(data[6]), u16::from_be(data[7]),
), bytes[16]))
}
_ => Err(Error::ParseError("Invalid address size"))
}
}
}
impl IpAddress {
pub fn from_str(addr: &str) -> Result<Self, Error> {
if let Some(pos) = addr.find("/") {
let prefix_len = try!(u8::from_str(&addr[pos+1..])
.map_err(|_| Error::ParseError("Failed to parse prefix length")));
let addr = &addr[..pos];
let ipv4 = Ipv4Addr::from_str(addr).map(|addr| IpAddress::V4Net(addr, prefix_len));
let ipv6 = Ipv6Addr::from_str(addr).map(|addr| IpAddress::V6Net(addr, prefix_len));
ipv4.or(ipv6).map_err(|_| Error::ParseError("Failed to parse address"))
} else {
let ipv4 = Ipv4Addr::from_str(addr).map(|addr| IpAddress::V4(addr));
let ipv6 = Ipv6Addr::from_str(addr).map(|addr| IpAddress::V6(addr));
ipv4.or(ipv6).map_err(|_| Error::ParseError("Failed to parse address"))
}
}
}
#[allow(dead_code)] #[allow(dead_code)]
pub struct InternetProtocol; pub struct InternetProtocol;
impl Protocol for InternetProtocol { impl Protocol for InternetProtocol {
type Address = IpAddress; fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
fn parse(data: &[u8]) -> Result<(IpAddress, IpAddress), Error> {
if data.len() < 1 { if data.len() < 1 {
return Err(Error::ParseError("Empty header")); return Err(Error::ParseError("Empty header"));
} }
@ -114,13 +19,13 @@ impl Protocol for InternetProtocol {
if data.len() < 20 { if data.len() < 20 {
return Err(Error::ParseError("Truncated header")); return Err(Error::ParseError("Truncated header"));
} }
Ok((try!(IpAddress::from_bytes(&data[12..16])), try!(IpAddress::from_bytes(&data[16..20])))) Ok((Address(to_vec(&data[12..16])), Address(to_vec(&data[16..20]))))
}, },
6 => { 6 => {
if data.len() < 40 { if data.len() < 40 {
return Err(Error::ParseError("Truncated header")); return Err(Error::ParseError("Truncated header"));
} }
Ok((try!(IpAddress::from_bytes(&data[8..24])), try!(IpAddress::from_bytes(&data[24..40])))) Ok((Address(to_vec(&data[8..24])), Address(to_vec(&data[24..40]))))
}, },
_ => Err(Error::ParseError("Invalid version")) _ => Err(Error::ParseError("Invalid version"))
} }
@ -128,7 +33,6 @@ impl Protocol for InternetProtocol {
} }
struct RoutingEntry { struct RoutingEntry {
address: SocketAddr, address: SocketAddr,
bytes: Vec<u8>, bytes: Vec<u8>,
@ -141,28 +45,34 @@ impl RoutingTable {
pub fn new() -> Self { pub fn new() -> Self {
RoutingTable(HashMap::new()) RoutingTable(HashMap::new())
} }
}
pub fn add(&mut self, bytes: Vec<u8>, prefix_len: u8, address: SocketAddr) { impl Table for RoutingTable {
fn learn(&mut self, addr: Address, prefix_len: Option<u8>, address: SocketAddr) {
let prefix_len = match prefix_len {
Some(val) => val,
None => addr.0.len() as u8 * 8
};
let group_len = (prefix_len as usize / 16) * 2; let group_len = (prefix_len as usize / 16) * 2;
let group_bytes: Vec<u8> = bytes[..group_len].iter().map(|b| *b).collect(); let group_bytes: Vec<u8> = addr.0[..group_len].iter().map(|b| *b).collect();
let routing_entry = RoutingEntry{address: address, bytes: bytes, prefix_len: prefix_len}; let routing_entry = RoutingEntry{address: address, bytes: addr.0, prefix_len: prefix_len};
match self.0.entry(group_bytes) { match self.0.entry(group_bytes) {
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry), hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () } hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () }
} }
} }
pub fn lookup_bytes(&self, bytes: &[u8]) -> Option<SocketAddr> { fn lookup(&self, addr: &Address) -> Option<SocketAddr> {
let len = bytes.len()/2 * 2; let len = addr.0.len()/2 * 2;
for i in 0..len/2 { for i in 0..len/2 {
if let Some(group) = self.0.get(&bytes[0..len-2*i]) { if let Some(group) = self.0.get(&addr.0[0..len-2*i]) {
for entry in group { for entry in group {
if entry.bytes.len() != bytes.len() { if entry.bytes.len() != addr.0.len() {
continue; continue;
} }
let mut match_len = 0; let mut match_len = 0;
for i in 0..bytes.len() { for i in 0..addr.0.len() {
let b = bytes[i] ^ entry.bytes[i]; let b = addr.0[i] ^ entry.bytes[i];
if b == 0 { if b == 0 {
match_len += 8; match_len += 8;
} else { } else {
@ -178,29 +88,6 @@ impl RoutingTable {
} }
None None
} }
}
impl Table for RoutingTable {
type Address = IpAddress;
fn learn(&mut self, src: Self::Address, addr: SocketAddr) {
match src {
IpAddress::V4(_) => (),
IpAddress::V4Net(base, prefix_len) => {
info!("Adding to routing table: {}/{} => {}", base, prefix_len, addr);
self.add(IpAddress::V4(base).to_bytes(), prefix_len, addr);
},
IpAddress::V6(_) => (),
IpAddress::V6Net(base, prefix_len) => {
info!("Adding to routing table: {}/{} => {}", base, prefix_len, addr);
self.add(IpAddress::V6(base).to_bytes(), prefix_len, addr);
}
}
}
fn lookup(&self, dst: &Self::Address) -> Option<SocketAddr> {
self.lookup_bytes(&dst.to_bytes())
}
fn housekeep(&mut self) { fn housekeep(&mut self) {
//nothin to do //nothin to do

View File

@ -2,9 +2,8 @@ use std::{mem, ptr, fmt};
use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr}; use std::net::{SocketAddr, SocketAddrV4, Ipv4Addr};
use std::u16; use std::u16;
use super::cloud::{Error, NetworkId, Address}; use super::cloud::{Error, NetworkId, Range, Address};
use super::util::{as_obj, as_bytes}; use super::util::{as_obj, as_bytes, to_vec};
#[cfg(test)] use super::ethernet;
const MAGIC: [u8; 3] = [0x76, 0x70, 0x6e]; const MAGIC: [u8; 3] = [0x76, 0x70, 0x6e];
const VERSION: u8 = 0; const VERSION: u8 = 0;
@ -31,14 +30,14 @@ pub struct Options {
#[derive(PartialEq)] #[derive(PartialEq)]
pub enum Message<'a, A: Address> { pub enum Message<'a> {
Data(&'a[u8]), Data(&'a[u8]),
Peers(Vec<SocketAddr>), Peers(Vec<SocketAddr>),
Init(Vec<A>), Init(Vec<Range>),
Close, Close,
} }
impl<'a, A: Address> fmt::Debug for Message<'a, A> { impl<'a> fmt::Debug for Message<'a> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match self { match self {
&Message::Data(ref data) => write!(formatter, "Data(data: {} bytes)", data.len()), &Message::Data(ref data) => write!(formatter, "Data(data: {} bytes)", data.len()),
@ -60,7 +59,7 @@ impl<'a, A: Address> fmt::Debug for Message<'a, A> {
} }
} }
pub fn decode<A: Address>(data: &[u8]) -> Result<(Options, Message<A>), Error> { pub fn decode(data: &[u8]) -> Result<(Options, Message), Error> {
if data.len() < mem::size_of::<TopHeader>() { if data.len() < mem::size_of::<TopHeader>() {
return Err(Error::ParseError("Empty message")); return Err(Error::ParseError("Empty message"));
} }
@ -125,8 +124,14 @@ pub fn decode<A: Address>(data: &[u8]) -> Result<(Options, Message<A>), Error> {
if data.len() < pos + len { if data.len() < pos + len {
return Err(Error::ParseError("Init data too short")); return Err(Error::ParseError("Init data too short"));
} }
addrs.push(try!(A::from_bytes(&data[pos..pos+len]))); let base = Address(to_vec(&data[pos..pos+len]));
pos += len; pos += len;
if data.len() < pos + 1 {
return Err(Error::ParseError("Init data too short"));
}
let prefix_len = data[pos];
pos += 1;
addrs.push(Range{base: base, prefix_len: prefix_len});
} }
Message::Init(addrs) Message::Init(addrs)
}, },
@ -136,7 +141,7 @@ pub fn decode<A: Address>(data: &[u8]) -> Result<(Options, Message<A>), Error> {
Ok((options, msg)) Ok((options, msg))
} }
pub fn encode<A: Address>(options: &Options, msg: &Message<A>, buf: &mut [u8]) -> usize { pub fn encode(options: &Options, msg: &Message, buf: &mut [u8]) -> usize {
assert!(buf.len() >= mem::size_of::<TopHeader>()); assert!(buf.len() >= mem::size_of::<TopHeader>());
let mut pos = 0; let mut pos = 0;
let mut header = TopHeader::default(); let mut header = TopHeader::default();
@ -192,19 +197,22 @@ pub fn encode<A: Address>(options: &Options, msg: &Message<A>, buf: &mut [u8]) -
buf[pos] = 0; buf[pos] = 0;
pos += 1; pos += 1;
}, },
&Message::Init(ref addrs) => { &Message::Init(ref ranges) => {
assert!(buf.len() >= pos + 1); assert!(buf.len() >= pos + 1);
assert!(addrs.len() <= 255); assert!(ranges.len() <= 255);
buf[pos] = addrs.len() as u8; buf[pos] = ranges.len() as u8;
pos += 1; pos += 1;
for addr in addrs { for range in ranges {
let bytes = addr.to_bytes(); let base = &range.base;
assert!(bytes.len() <= 255); let len = base.0.len();
assert!(buf.len() >= pos + 1 + bytes.len()); assert!(len <= 255);
buf[pos] = bytes.len() as u8; assert!(buf.len() >= pos + 1 + len + 1);
buf[pos] = len as u8;
pos += 1;
unsafe { ptr::copy_nonoverlapping(base.0.as_ptr(), buf[pos..].as_mut_ptr(), base.0.len()) };
pos += base.0.len();
buf[pos] = range.prefix_len;
pos += 1; pos += 1;
unsafe { ptr::copy_nonoverlapping(bytes.as_ptr(), buf[pos..].as_mut_ptr(), bytes.len()) };
pos += bytes.len();
} }
}, },
&Message::Close => { &Message::Close => {
@ -218,7 +226,7 @@ pub fn encode<A: Address>(options: &Options, msg: &Message<A>, buf: &mut [u8]) -
fn encode_message_packet() { fn encode_message_packet() {
let options = Options::default(); let options = Options::default();
let payload = [1,2,3,4,5]; let payload = [1,2,3,4,5];
let msg: Message<ethernet::EthAddr> = Message::Data(&payload); let msg = Message::Data(&payload);
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let size = encode(&options, &msg, &mut buf[..]); let size = encode(&options, &msg, &mut buf[..]);
assert_eq!(size, 13); assert_eq!(size, 13);
@ -232,7 +240,7 @@ fn encode_message_packet() {
fn encode_message_peers() { fn encode_message_peers() {
use std::str::FromStr; use std::str::FromStr;
let options = Options::default(); let options = Options::default();
let msg: Message<ethernet::EthAddr> = Message::Peers(vec![SocketAddr::from_str("1.2.3.4:123").unwrap(), SocketAddr::from_str("5.6.7.8:12345").unwrap()]); let msg = Message::Peers(vec![SocketAddr::from_str("1.2.3.4:123").unwrap(), SocketAddr::from_str("5.6.7.8:12345").unwrap()]);
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let size = encode(&options, &msg, &mut buf[..]); let size = encode(&options, &msg, &mut buf[..]);
assert_eq!(size, 22); assert_eq!(size, 22);
@ -246,7 +254,7 @@ fn encode_message_peers() {
fn encode_option_network_id() { fn encode_option_network_id() {
let mut options = Options::default(); let mut options = Options::default();
options.network_id = Some(134); options.network_id = Some(134);
let msg: Message<ethernet::EthAddr> = Message::Close; let msg = Message::Close;
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let size = encode(&options, &msg, &mut buf[..]); let size = encode(&options, &msg, &mut buf[..]);
assert_eq!(size, 16); assert_eq!(size, 16);
@ -260,7 +268,7 @@ fn encode_option_network_id() {
fn encode_message_init() { fn encode_message_init() {
let options = Options::default(); let options = Options::default();
let addrs = vec![]; let addrs = vec![];
let msg: Message<ethernet::EthAddr> = Message::Init(addrs); let msg = Message::Init(addrs);
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let size = encode(&options, &msg, &mut buf[..]); let size = encode(&options, &msg, &mut buf[..]);
assert_eq!(size, 13); assert_eq!(size, 13);
@ -273,7 +281,7 @@ fn encode_message_init() {
#[test] #[test]
fn encode_message_close() { fn encode_message_close() {
let options = Options::default(); let options = Options::default();
let msg: Message<ethernet::EthAddr> = Message::Close; let msg = Message::Close;
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let size = encode(&options, &msg, &mut buf[..]); let size = encode(&options, &msg, &mut buf[..]);
assert_eq!(size, 8); assert_eq!(size, 8);

View File

@ -1,4 +1,4 @@
use std::{mem, slice}; use std::{mem, slice, ptr};
#[inline(always)] #[inline(always)]
pub unsafe fn as_bytes<T>(obj: &T) -> &[u8] { pub unsafe fn as_bytes<T>(obj: &T) -> &[u8] {
@ -10,3 +10,12 @@ pub unsafe fn as_obj<T>(data: &[u8]) -> &T {
assert!(data.len() >= mem::size_of::<T>()); assert!(data.len() >= mem::size_of::<T>());
mem::transmute(data.as_ptr()) mem::transmute(data.as_ptr())
} }
pub fn to_vec(data: &[u8]) -> Vec<u8> {
let mut v = Vec::with_capacity(data.len());
unsafe {
ptr::copy_nonoverlapping(data.as_ptr(), v.as_mut_ptr(), data.len());
v.set_len(data.len());
}
v
}