From 8716c70e6dffb3e3250df485b7d010da786f9db3 Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Sun, 22 Nov 2015 19:47:28 +0100 Subject: [PATCH] Routing table from file --- Cargo.toml | 1 + src/ip.rs | 106 +++++++++++++++++++++++++++++++++++++++++++--------- src/main.rs | 1 + 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d57e6e2..d645e0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ docopt = "0.6" rustc-serialize = "0.3" log = "0.3" epoll = "0.2" +regex = "0.1" [build-dependencies] gcc = "0.3" diff --git a/src/ip.rs b/src/ip.rs index 94cb3ae..708a99b 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -1,6 +1,12 @@ -use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr}; +use std::net::{SocketAddr, Ipv4Addr, Ipv6Addr, AddrParseError, ToSocketAddrs}; use std::collections::{hash_map, HashMap}; use std::ptr; +use std::path::Path; +use std::fs::File; +use std::io::{Result as IoResult, Read, BufRead, BufReader}; +use std::str::FromStr; + +use regex::Regex; use super::cloud::{Protocol, Error, Table}; use super::util::{as_obj, as_bytes}; @@ -12,6 +18,42 @@ pub enum IpAddress { V6(Ipv6Addr) } +impl IpAddress { + pub fn to_bytes(&self) -> Vec { + 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::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 + } + } + } + + pub fn from_str(addr: &str) -> Result { + 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) + } +} + + pub struct InternetProtocol; impl Protocol for InternetProtocol { @@ -83,8 +125,51 @@ impl RoutingTable { } } + pub fn load_from(&mut self, path: &Path) -> IoResult<()> { + let pattern = Regex::new(r"(?P[^/]+)/(?P\d+)\s=>\s(?P.+)").unwrap(); + let file = try!(File::open(path)); + let mut reader = BufReader::new(file); + loop { + let mut s = String::new(); + let res = try!(reader.read_line(&mut s)); + if res == 0 { + break; + } + let captures = match pattern.captures(&s) { + Some(captures) => captures, + None => { + error!("Failed to parse routing table entry: {}", s); + continue + } + }; + let base = match IpAddress::from_str(captures.name("base").unwrap()) { + Ok(addr) => addr.to_bytes(), + Err(e) => { + error!("Failed to parse base address: {}", e); + continue + } + }; + let prefix_len = match u8::from_str(captures.name("prefix").unwrap()) { + Ok(num) => num, + Err(e) => { + error!("Failed to parse prefix length: {}", e); + continue + } + }; + let peer = match captures.name("peer").unwrap().to_socket_addrs().map(|mut r| r.next()) { + Ok(Some(addr)) => addr, + _ => { + error!("Failed to parse peer address"); + continue + } + }; + self.add(base, prefix_len, peer); + } + Ok(()) + } + pub fn lookup_bytes(&self, bytes: &[u8]) -> Option { - let mut len = bytes.len()/2 * 2; + let 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 { @@ -119,22 +204,7 @@ impl Table for RoutingTable { } fn lookup(&self, dst: &Self::Address) -> Option { - match dst { - &IpAddress::V4(addr) => { - let mut bytes = [0u8; 4]; - let ip = addr.octets(); - unsafe { ptr::copy_nonoverlapping(ip.as_ptr(), bytes.as_mut_ptr(), ip.len()) }; - self.lookup_bytes(&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) }; - self.lookup_bytes(bytes) - } - } + self.lookup_bytes(&dst.to_bytes()) } fn housekeep(&mut self) { diff --git a/src/main.rs b/src/main.rs index 51f78af..5dfea2d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate time; extern crate docopt; extern crate rustc_serialize; extern crate epoll; +extern crate regex; mod util; mod udpmessage;