Move common definitions into netutils
This commit is contained in:
parent
63cff7bc48
commit
d0abe6335a
21 changed files with 64 additions and 808 deletions
|
@ -1,275 +0,0 @@
|
|||
use std::{mem, slice, u8, u16};
|
||||
|
||||
pub static mut MAC_ADDR: MacAddr = MacAddr { bytes: [0x50, 0x51, 0x52, 0x53, 0x54, 0x55] };
|
||||
pub static BROADCAST_MAC_ADDR: MacAddr = MacAddr { bytes: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] };
|
||||
|
||||
pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] };
|
||||
pub static mut IP_ROUTER_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 2] };
|
||||
pub static mut IP_SUBNET: Ipv4Addr = Ipv4Addr { bytes: [255, 255, 255, 0] };
|
||||
pub static BROADCAST_IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [255, 255, 255, 255] };
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[repr(packed)]
|
||||
pub struct n16(u16);
|
||||
|
||||
impl n16 {
|
||||
pub fn new(value: u16) -> Self {
|
||||
n16(value.to_be())
|
||||
}
|
||||
|
||||
pub fn get(&self) -> u16 {
|
||||
u16::from_be(self.0)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: u16) {
|
||||
self.0 = value.to_be();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MacAddr {
|
||||
pub bytes: [u8; 6],
|
||||
}
|
||||
|
||||
impl MacAddr {
|
||||
pub fn equals(&self, other: Self) -> bool {
|
||||
for i in 0..6 {
|
||||
if self.bytes[i] != other.bytes[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Self {
|
||||
let mut addr = MacAddr { bytes: [0, 0, 0, 0, 0, 0] };
|
||||
|
||||
let mut i = 0;
|
||||
for part in string.split('.') {
|
||||
let octet = u8::from_str_radix(part, 16).unwrap_or(0);
|
||||
match i {
|
||||
0 => addr.bytes[0] = octet,
|
||||
1 => addr.bytes[1] = octet,
|
||||
2 => addr.bytes[2] = octet,
|
||||
3 => addr.bytes[3] = octet,
|
||||
4 => addr.bytes[4] = octet,
|
||||
5 => addr.bytes[5] = octet,
|
||||
_ => break,
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
let mut string = String::new();
|
||||
for i in 0..6 {
|
||||
if i > 0 {
|
||||
string.push('.');
|
||||
}
|
||||
string.push_str(&format!("{:X}", self.bytes[i]));
|
||||
}
|
||||
string
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Ipv4Addr {
|
||||
pub bytes: [u8; 4],
|
||||
}
|
||||
|
||||
impl Ipv4Addr {
|
||||
pub fn equals(&self, other: Self) -> bool {
|
||||
for i in 0..4 {
|
||||
if self.bytes[i] != other.bytes[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
pub fn from_str(string: &str) -> Self {
|
||||
let mut addr = Ipv4Addr { bytes: [0, 0, 0, 0] };
|
||||
|
||||
let mut i = 0;
|
||||
for part in string.split('.') {
|
||||
let octet = part.parse::<u8>().unwrap_or(0);
|
||||
match i {
|
||||
0 => addr.bytes[0] = octet,
|
||||
1 => addr.bytes[1] = octet,
|
||||
2 => addr.bytes[2] = octet,
|
||||
3 => addr.bytes[3] = octet,
|
||||
_ => break,
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
let mut string = String::new();
|
||||
|
||||
for i in 0..4 {
|
||||
if i > 0 {
|
||||
string = string + ".";
|
||||
}
|
||||
string = string + &format!("{}", self.bytes[i]);
|
||||
}
|
||||
|
||||
string
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Checksum {
|
||||
pub data: u16,
|
||||
}
|
||||
|
||||
impl Checksum {
|
||||
pub unsafe fn check(&self, mut ptr: usize, mut len: usize) -> bool {
|
||||
let mut sum: usize = 0;
|
||||
while len > 1 {
|
||||
sum += *(ptr as *const u16) as usize;
|
||||
len -= 2;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
if len > 0 {
|
||||
sum += *(ptr as *const u8) as usize;
|
||||
}
|
||||
|
||||
while (sum >> 16) > 0 {
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
}
|
||||
|
||||
sum == 0xFFFF
|
||||
}
|
||||
|
||||
pub unsafe fn calculate(&mut self, ptr: usize, len: usize) {
|
||||
self.data = 0;
|
||||
|
||||
let sum = Checksum::sum(ptr, len);
|
||||
|
||||
self.data = Checksum::compile(sum);
|
||||
}
|
||||
|
||||
pub unsafe fn sum(mut ptr: usize, mut len: usize) -> usize {
|
||||
let mut sum = 0;
|
||||
|
||||
while len > 1 {
|
||||
sum += *(ptr as *const u16) as usize;
|
||||
len -= 2;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
if len > 0 {
|
||||
sum += *(ptr as *const u8) as usize;
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
pub fn compile(mut sum: usize) -> u16 {
|
||||
while (sum >> 16) > 0 {
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
}
|
||||
|
||||
0xFFFF - (sum as u16)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(packed)]
|
||||
pub struct ArpHeader {
|
||||
pub htype: n16,
|
||||
pub ptype: n16,
|
||||
pub hlen: u8,
|
||||
pub plen: u8,
|
||||
pub oper: n16,
|
||||
pub src_mac: MacAddr,
|
||||
pub src_ip: Ipv4Addr,
|
||||
pub dst_mac: MacAddr,
|
||||
pub dst_ip: Ipv4Addr,
|
||||
}
|
||||
|
||||
pub struct Arp {
|
||||
pub header: ArpHeader,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Arp {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||
if bytes.len() >= mem::size_of::<ArpHeader>() {
|
||||
unsafe {
|
||||
return Some(Arp {
|
||||
header: *(bytes.as_ptr() as *const ArpHeader),
|
||||
data: bytes[mem::size_of::<ArpHeader>() ..].to_vec(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let header_ptr: *const ArpHeader = &self.header;
|
||||
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
|
||||
mem::size_of::<ArpHeader>()));
|
||||
ret.extend_from_slice(&self.data);
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(packed)]
|
||||
pub struct Ipv4Header {
|
||||
pub ver_hlen: u8,
|
||||
pub services: u8,
|
||||
pub len: n16,
|
||||
pub id: n16,
|
||||
pub flags_fragment: n16,
|
||||
pub ttl: u8,
|
||||
pub proto: u8,
|
||||
pub checksum: Checksum,
|
||||
pub src: Ipv4Addr,
|
||||
pub dst: Ipv4Addr,
|
||||
}
|
||||
|
||||
pub struct Ipv4 {
|
||||
pub header: Ipv4Header,
|
||||
pub options: Vec<u8>,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Ipv4 {
|
||||
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
|
||||
if bytes.len() >= mem::size_of::<Ipv4Header>() {
|
||||
unsafe {
|
||||
let header = *(bytes.as_ptr() as *const Ipv4Header);
|
||||
let header_len = ((header.ver_hlen & 0xF) << 2) as usize;
|
||||
|
||||
return Some(Ipv4 {
|
||||
header: header,
|
||||
options: bytes[mem::size_of::<Ipv4Header>() .. header_len].to_vec(),
|
||||
data: bytes[header_len .. header.len.get() as usize].to_vec(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
unsafe {
|
||||
let header_ptr: *const Ipv4Header = &self.header;
|
||||
let mut ret = Vec::<u8>::from(slice::from_raw_parts(header_ptr as *const u8,
|
||||
mem::size_of::<Ipv4Header>()));
|
||||
ret.extend_from_slice(&self.options);
|
||||
ret.extend_from_slice(&self.data);
|
||||
ret
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(rand)]
|
||||
|
||||
extern crate netutils;
|
||||
extern crate resource_scheme;
|
||||
extern crate syscall;
|
||||
|
||||
|
@ -12,9 +13,8 @@ use syscall::Packet;
|
|||
|
||||
use scheme::IpScheme;
|
||||
|
||||
pub mod common;
|
||||
pub mod resource;
|
||||
pub mod scheme;
|
||||
mod resource;
|
||||
mod scheme;
|
||||
|
||||
fn main() {
|
||||
thread::spawn(move || {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use std::{cmp, mem};
|
||||
|
||||
use netutils::{n16, Ipv4Addr, Checksum, Ipv4Header, Ipv4};
|
||||
use resource_scheme::Resource;
|
||||
use syscall;
|
||||
use syscall::error::*;
|
||||
|
||||
use common::{n16, Ipv4Addr, Checksum, Ipv4Header, Ipv4, IP_ADDR, BROADCAST_IP_ADDR};
|
||||
|
||||
/// A IP (internet protocole) resource
|
||||
pub struct IpResource {
|
||||
pub link: usize,
|
||||
pub data: Vec<u8>,
|
||||
pub host_addr: Ipv4Addr,
|
||||
pub peer_addr: Ipv4Addr,
|
||||
pub proto: u8,
|
||||
pub id: u16,
|
||||
|
@ -21,6 +21,7 @@ impl Resource for IpResource {
|
|||
Ok(Box::new(IpResource {
|
||||
link: link,
|
||||
data: self.data.clone(),
|
||||
host_addr: self.host_addr,
|
||||
peer_addr: self.peer_addr,
|
||||
proto: self.proto,
|
||||
id: self.id,
|
||||
|
@ -55,8 +56,8 @@ impl Resource for IpResource {
|
|||
|
||||
if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
|
||||
if packet.header.proto == self.proto &&
|
||||
(packet.header.dst.equals(unsafe { IP_ADDR }) || packet.header.dst.equals(BROADCAST_IP_ADDR)) &&
|
||||
(packet.header.src.equals(self.peer_addr) || self.peer_addr.equals(BROADCAST_IP_ADDR)) {
|
||||
(packet.header.dst.equals(self.host_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) &&
|
||||
(packet.header.src.equals(self.peer_addr) || self.peer_addr.equals(Ipv4Addr::BROADCAST)) {
|
||||
for (b, d) in buf.iter_mut().zip(packet.data.iter()) {
|
||||
*b = *d;
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ impl Resource for IpResource {
|
|||
ttl: 128,
|
||||
proto: self.proto,
|
||||
checksum: Checksum { data: 0 },
|
||||
src: unsafe { IP_ADDR },
|
||||
src: self.host_addr,
|
||||
dst: self.peer_addr,
|
||||
},
|
||||
options: Vec::new(),
|
||||
|
|
|
@ -2,12 +2,12 @@ use std::cell::RefCell;
|
|||
use std::rand;
|
||||
use std::{str, u16};
|
||||
|
||||
use netutils::{getcfg, n16, MacAddr, Ipv4Addr, ArpHeader, Arp, Ipv4};
|
||||
use resource_scheme::ResourceScheme;
|
||||
use syscall;
|
||||
use syscall::error::{Error, Result, EACCES, ENOENT, EINVAL};
|
||||
use syscall::flag::O_RDWR;
|
||||
|
||||
use common::{n16, MacAddr, Ipv4Addr, ArpHeader, Arp, Ipv4, MAC_ADDR, BROADCAST_MAC_ADDR, BROADCAST_IP_ADDR, IP_ADDR, IP_ROUTER_ADDR, IP_SUBNET};
|
||||
use resource::IpResource;
|
||||
|
||||
/// A ARP entry (MAC + IP)
|
||||
|
@ -32,6 +32,11 @@ impl IpScheme {
|
|||
impl ResourceScheme<IpResource> for IpScheme {
|
||||
fn open_resource(&self, url: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result<Box<IpResource>> {
|
||||
if uid == 0 {
|
||||
let mac_addr = MacAddr::from_str(&getcfg("mac").map_err(|err| err.into_sys())?);
|
||||
let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
|
||||
let ip_subnet = Ipv4Addr::from_str(&getcfg("ip_subnet").map_err(|err| err.into_sys())?);
|
||||
let ip_router = Ipv4Addr::from_str(&getcfg("ip_router").map_err(|err| err.into_sys())?);
|
||||
|
||||
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
|
||||
let mut parts = path.split('/');
|
||||
if let Some(host_string) = parts.next() {
|
||||
|
@ -40,14 +45,14 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
|
||||
if ! host_string.is_empty() {
|
||||
let peer_addr = Ipv4Addr::from_str(host_string);
|
||||
let mut route_mac = BROADCAST_MAC_ADDR;
|
||||
let mut route_mac = MacAddr::BROADCAST;
|
||||
|
||||
if ! peer_addr.equals(BROADCAST_IP_ADDR) {
|
||||
if ! peer_addr.equals(Ipv4Addr::BROADCAST) {
|
||||
let mut needs_routing = false;
|
||||
|
||||
for octet in 0..4 {
|
||||
let me = unsafe { IP_ADDR.bytes[octet] };
|
||||
let mask = unsafe { IP_SUBNET.bytes[octet] };
|
||||
let me = ip_addr.bytes[octet];
|
||||
let mask = ip_subnet.bytes[octet];
|
||||
let them = peer_addr.bytes[octet];
|
||||
if me & mask != them & mask {
|
||||
needs_routing = true;
|
||||
|
@ -56,7 +61,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
}
|
||||
|
||||
let route_addr = if needs_routing {
|
||||
unsafe { IP_ROUTER_ADDR }
|
||||
ip_router
|
||||
} else {
|
||||
peer_addr
|
||||
};
|
||||
|
@ -68,7 +73,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
}
|
||||
}
|
||||
|
||||
if route_mac.equals(BROADCAST_MAC_ADDR) {
|
||||
if route_mac.equals(MacAddr::BROADCAST) {
|
||||
if let Ok(link) = syscall::open(&format!("ethernet:{}/806", &route_mac.to_string()), O_RDWR) {
|
||||
let arp = Arp {
|
||||
header: ArpHeader {
|
||||
|
@ -77,8 +82,8 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
hlen: 6,
|
||||
plen: 4,
|
||||
oper: n16::new(1),
|
||||
src_mac: unsafe { MAC_ADDR },
|
||||
src_ip: unsafe { IP_ADDR },
|
||||
src_mac: mac_addr,
|
||||
src_ip: ip_addr,
|
||||
dst_mac: route_mac,
|
||||
dst_ip: route_addr,
|
||||
},
|
||||
|
@ -113,6 +118,7 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
return Ok(Box::new(IpResource {
|
||||
link: link,
|
||||
data: Vec::new(),
|
||||
host_addr: ip_addr,
|
||||
peer_addr: peer_addr,
|
||||
proto: proto,
|
||||
id: (rand() % 65536) as u16,
|
||||
|
@ -125,10 +131,11 @@ impl ResourceScheme<IpResource> for IpScheme {
|
|||
Ok(count) => {
|
||||
if let Some(packet) = Ipv4::from_bytes(&bytes[..count]) {
|
||||
if packet.header.proto == proto &&
|
||||
(packet.header.dst.equals(unsafe { IP_ADDR }) || packet.header.dst.equals(BROADCAST_IP_ADDR)) {
|
||||
(packet.header.dst.equals(ip_addr) || packet.header.dst.equals(Ipv4Addr::BROADCAST)) {
|
||||
return Ok(Box::new(IpResource {
|
||||
link: link,
|
||||
data: packet.data,
|
||||
host_addr: ip_addr,
|
||||
peer_addr: packet.header.src,
|
||||
proto: proto,
|
||||
id: (rand() % 65536) as u16,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue