2016-02-05 15:58:32 +00:00
|
|
|
// VpnCloud - Peer-to-Peer VPN
|
|
|
|
// Copyright (C) 2015-2016 Dennis Schwerdel
|
|
|
|
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
|
|
|
|
2015-11-22 23:49:58 +00:00
|
|
|
use std::net::SocketAddr;
|
2015-11-21 15:50:50 +00:00
|
|
|
use std::collections::{hash_map, HashMap};
|
2015-11-22 21:00:34 +00:00
|
|
|
use std::io::Read;
|
2016-03-29 08:45:54 +00:00
|
|
|
use std::hash::BuildHasherDefault;
|
|
|
|
|
|
|
|
use fnv::FnvHasher;
|
2015-11-22 18:47:28 +00:00
|
|
|
|
2015-11-23 00:04:30 +00:00
|
|
|
use super::types::{Protocol, Error, Table, Address};
|
2015-11-25 20:05:11 +00:00
|
|
|
|
2015-11-22 18:47:28 +00:00
|
|
|
|
2015-11-22 19:02:02 +00:00
|
|
|
#[allow(dead_code)]
|
2015-11-23 00:40:47 +00:00
|
|
|
pub struct Packet;
|
2015-11-22 16:28:04 +00:00
|
|
|
|
2015-11-23 00:40:47 +00:00
|
|
|
impl Protocol for Packet {
|
2015-11-22 23:49:58 +00:00
|
|
|
fn parse(data: &[u8]) -> Result<(Address, Address), Error> {
|
2015-11-22 18:00:56 +00:00
|
|
|
if data.len() < 1 {
|
|
|
|
return Err(Error::ParseError("Empty header"));
|
|
|
|
}
|
|
|
|
let version = data[0] >> 4;
|
|
|
|
match version {
|
|
|
|
4 => {
|
2015-11-29 22:23:39 +00:00
|
|
|
if data.len() < 20 {
|
|
|
|
return Err(Error::ParseError("Truncated IPv4 header"));
|
|
|
|
}
|
2015-11-26 09:45:25 +00:00
|
|
|
let src = try!(Address::read_from_fixed(&data[12..], 4));
|
|
|
|
let dst = try!(Address::read_from_fixed(&data[16..], 4));
|
|
|
|
Ok((src, dst))
|
2015-11-22 18:00:56 +00:00
|
|
|
},
|
|
|
|
6 => {
|
2015-11-29 22:23:39 +00:00
|
|
|
if data.len() < 40 {
|
|
|
|
return Err(Error::ParseError("Truncated IPv6 header"));
|
|
|
|
}
|
2015-11-26 09:45:25 +00:00
|
|
|
let src = try!(Address::read_from_fixed(&data[8..], 16));
|
|
|
|
let dst = try!(Address::read_from_fixed(&data[24..], 16));
|
|
|
|
Ok((src, dst))
|
2015-11-22 18:00:56 +00:00
|
|
|
},
|
|
|
|
_ => Err(Error::ParseError("Invalid version"))
|
|
|
|
}
|
2015-11-22 16:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-21 15:50:50 +00:00
|
|
|
struct RoutingEntry {
|
|
|
|
address: SocketAddr,
|
2015-11-25 20:05:11 +00:00
|
|
|
bytes: [u8; 16],
|
2015-11-21 15:50:50 +00:00
|
|
|
prefix_len: u8
|
|
|
|
}
|
|
|
|
|
2016-03-29 08:45:54 +00:00
|
|
|
type Hash = BuildHasherDefault<FnvHasher>;
|
|
|
|
|
|
|
|
pub struct RoutingTable(HashMap<Vec<u8>, Vec<RoutingEntry>, Hash>);
|
2015-11-21 15:50:50 +00:00
|
|
|
|
|
|
|
impl RoutingTable {
|
|
|
|
pub fn new() -> Self {
|
2016-03-29 08:45:54 +00:00
|
|
|
RoutingTable(HashMap::default())
|
2015-11-21 15:50:50 +00:00
|
|
|
}
|
2015-11-22 23:49:58 +00:00
|
|
|
}
|
2015-11-21 15:50:50 +00:00
|
|
|
|
2015-11-22 23:49:58 +00:00
|
|
|
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,
|
2015-11-26 09:45:25 +00:00
|
|
|
None => addr.len * 8
|
2015-11-22 23:49:58 +00:00
|
|
|
};
|
2015-11-26 21:16:51 +00:00
|
|
|
info!("New routing entry: {}/{} => {}", addr, prefix_len, address);
|
|
|
|
let group_len = prefix_len as usize / 8;
|
2015-11-25 20:05:11 +00:00
|
|
|
assert!(group_len <= 16);
|
2015-11-26 21:16:51 +00:00
|
|
|
let mut group_bytes = Vec::with_capacity(group_len);
|
2015-11-26 09:45:25 +00:00
|
|
|
for i in 0..group_len {
|
2015-11-26 21:16:51 +00:00
|
|
|
group_bytes.push(addr.data[i]);
|
2015-11-26 09:45:25 +00:00
|
|
|
}
|
|
|
|
let routing_entry = RoutingEntry{address: address, bytes: addr.data, prefix_len: prefix_len};
|
2015-11-21 15:50:50 +00:00
|
|
|
match self.0.entry(group_bytes) {
|
|
|
|
hash_map::Entry::Occupied(mut entry) => entry.get_mut().push(routing_entry),
|
|
|
|
hash_map::Entry::Vacant(entry) => { entry.insert(vec![routing_entry]); () }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-25 18:23:25 +00:00
|
|
|
fn lookup(&mut self, addr: &Address) -> Option<SocketAddr> {
|
2015-11-26 21:16:51 +00:00
|
|
|
let len = addr.len as usize;
|
|
|
|
let mut found = None;
|
|
|
|
let mut found_len: isize = -1;
|
|
|
|
for i in 0..len+1 {
|
|
|
|
if let Some(group) = self.0.get(&addr.data[0..len-i]) {
|
2015-11-21 15:50:50 +00:00
|
|
|
for entry in group {
|
|
|
|
let mut match_len = 0;
|
2015-11-26 09:45:25 +00:00
|
|
|
for j in 0..addr.len as usize {
|
|
|
|
let b = addr.data[j] ^ entry.bytes[j];
|
2015-11-21 15:50:50 +00:00
|
|
|
if b == 0 {
|
|
|
|
match_len += 8;
|
|
|
|
} else {
|
|
|
|
match_len += b.leading_zeros();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-11-26 21:16:51 +00:00
|
|
|
if match_len as u8 >= entry.prefix_len && match_len as isize > found_len {
|
|
|
|
found = Some(entry.address);
|
|
|
|
found_len = match_len as isize;
|
2015-11-21 15:50:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-11-26 21:16:51 +00:00
|
|
|
found
|
2015-11-21 15:50:50 +00:00
|
|
|
}
|
2015-11-22 18:00:56 +00:00
|
|
|
|
|
|
|
fn housekeep(&mut self) {
|
2015-11-25 11:29:12 +00:00
|
|
|
//nothing to do
|
2015-11-22 18:00:56 +00:00
|
|
|
}
|
2015-11-22 21:00:34 +00:00
|
|
|
|
|
|
|
fn remove_all(&mut self, _addr: SocketAddr) {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
2015-11-22 18:00:56 +00:00
|
|
|
}
|