2015-11-22 16:28:04 +00:00
|
|
|
use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr};
|
2015-11-21 15:50:50 +00:00
|
|
|
use std::collections::{hash_map, HashMap};
|
2015-11-22 16:28:04 +00:00
|
|
|
use std::fmt;
|
|
|
|
|
|
|
|
use super::cloud::{InterfaceMessage, Error};
|
|
|
|
use super::util::{as_obj, as_bytes};
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
pub enum IpAddress {
|
|
|
|
V4(Ipv4Addr),
|
|
|
|
V6(Ipv6Addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(PartialEq)]
|
|
|
|
pub enum IpHeader {
|
|
|
|
V4{src: Ipv4Addr, dst: Ipv4Addr},
|
|
|
|
V6{src: Ipv6Addr, dst: Ipv6Addr}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for IpHeader {
|
|
|
|
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
|
|
|
match self {
|
|
|
|
&IpHeader::V4{src, dst} => write!(formatter, "src: {}, dst: {}", src, dst),
|
|
|
|
&IpHeader::V6{src, dst} => write!(formatter, "src: {}, dst: {}", src, dst)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl InterfaceMessage for IpHeader {
|
|
|
|
type Address = IpAddress;
|
|
|
|
|
|
|
|
fn src(&self) -> Self::Address {
|
|
|
|
match self {
|
|
|
|
&IpHeader::V4{src, dst: _} => IpAddress::V4(src),
|
|
|
|
&IpHeader::V6{src, dst: _} => IpAddress::V6(src)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dst(&self) -> Self::Address {
|
|
|
|
match self {
|
|
|
|
&IpHeader::V4{src: _, dst} => IpAddress::V4(dst),
|
|
|
|
&IpHeader::V6{src: _, dst} => IpAddress::V6(dst)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn encode_to(&self, payload: &[u8], data: &mut [u8]) -> usize {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_from(data: &[u8]) -> Result<(Self, &[u8]), Error> {
|
|
|
|
unimplemented!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-21 15:50:50 +00:00
|
|
|
|
|
|
|
struct RoutingEntry {
|
|
|
|
address: SocketAddr,
|
|
|
|
bytes: Vec<u8>,
|
|
|
|
prefix_len: u8
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct RoutingTable(HashMap<Vec<u8>, Vec<RoutingEntry>>);
|
|
|
|
|
|
|
|
impl RoutingTable {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
RoutingTable(HashMap::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add(&mut self, bytes: Vec<u8>, prefix_len: u8, address: SocketAddr) {
|
|
|
|
let group_len = (prefix_len as usize / 16) * 2;
|
|
|
|
let group_bytes: Vec<u8> = bytes[..group_len].iter().map(|b| *b).collect();
|
|
|
|
let routing_entry = RoutingEntry{address: address, bytes: bytes, prefix_len: prefix_len};
|
|
|
|
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]); () }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lookup(&self, bytes: Vec<u8>) -> Option<SocketAddr> {
|
|
|
|
let mut len = bytes.len()/2 * 2;
|
|
|
|
for i in 0..len/2 {
|
|
|
|
if let Some(group) = self.0.get(&bytes[0..len-2*i]) {
|
|
|
|
for entry in group {
|
|
|
|
if entry.bytes.len() != bytes.len() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let mut match_len = 0;
|
|
|
|
for i in 0..bytes.len() {
|
|
|
|
let b = bytes[i] ^ entry.bytes[i];
|
|
|
|
if b == 0 {
|
|
|
|
match_len += 8;
|
|
|
|
} else {
|
|
|
|
match_len += b.leading_zeros();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if match_len as u8 >= entry.prefix_len {
|
|
|
|
return Some(entry.address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|