Move common definitions into netutils

This commit is contained in:
Jeremy Soller 2016-10-20 17:49:54 -06:00
parent 63cff7bc48
commit d0abe6335a
21 changed files with 64 additions and 808 deletions

@ -1 +1 @@
Subproject commit 25c136612217ade85a0ca64ddfe3f95e5086b593
Subproject commit a45673aa948fe6d172a0e2b42ade86e0567c3afd

View file

@ -3,5 +3,6 @@ name = "ethernetd"
version = "0.1.0"
[dependencies]
netutils = { path = "../../programs/netutils/" }
resource_scheme = { path = "../../crates/resource_scheme/" }
syscall = { path = "../../syscall/" }

View file

@ -1,105 +0,0 @@
use std::{mem, slice, u8, u16};
#[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)]
#[repr(packed)]
pub struct EthernetIIHeader {
pub dst: MacAddr,
pub src: MacAddr,
pub ethertype: n16,
}
pub struct EthernetII {
pub header: EthernetIIHeader,
pub data: Vec<u8>,
}
impl EthernetII {
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() >= mem::size_of::<EthernetIIHeader>() {
unsafe {
return Some(EthernetII {
header: *(bytes.as_ptr() as *const EthernetIIHeader),
data: bytes[mem::size_of::<EthernetIIHeader>() ..].to_vec(),
});
}
}
None
}
pub fn to_bytes(&self) -> Vec<u8> {
unsafe {
let header_ptr: *const EthernetIIHeader = &self.header;
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
mem::size_of::<EthernetIIHeader>()));
ret.extend_from_slice(&self.data);
ret
}
}
}

View file

@ -1,3 +1,4 @@
extern crate netutils;
extern crate resource_scheme;
extern crate syscall;
@ -10,9 +11,8 @@ use syscall::Packet;
use scheme::EthernetScheme;
pub mod common;
pub mod resource;
pub mod scheme;
mod resource;
mod scheme;
fn main() {
thread::spawn(move || {

View file

@ -1,11 +1,10 @@
use std::{cmp, mem};
use netutils::{n16, MacAddr, EthernetIIHeader, EthernetII};
use resource_scheme::Resource;
use syscall;
use syscall::error::*;
use common::{n16, MacAddr, EthernetIIHeader, EthernetII};
/// A ethernet resource
pub struct EthernetResource {
/// The network

View file

@ -1,11 +1,11 @@
use std::{str, u16};
use netutils::{MacAddr, EthernetII};
use resource_scheme::ResourceScheme;
use syscall;
use syscall::error::{Error, Result, EACCES, ENOENT, EINVAL};
use syscall::flag::O_RDWR;
use common::{MacAddr, EthernetII};
use resource::EthernetResource;
pub struct EthernetScheme;

View file

@ -3,5 +3,6 @@ name = "ipd"
version = "0.1.0"
[dependencies]
netutils = { path = "../../programs/netutils/" }
resource_scheme = { path = "../../crates/resource_scheme/" }
syscall = { path = "../../syscall/" }

View file

@ -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
}
}
}

View file

@ -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 || {

View file

@ -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(),

View file

@ -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,

View file

@ -3,5 +3,6 @@ name = "tcpd"
version = "0.1.0"
[dependencies]
netutils = { path = "../../programs/netutils/" }
resource_scheme = { path = "../../crates/resource_scheme/" }
syscall = { path = "../../syscall/" }

View file

@ -1,217 +0,0 @@
use std::{mem, slice, u8, u16, u32};
pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] };
#[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)]
#[allow(non_camel_case_types)]
#[repr(packed)]
pub struct n32(u32);
impl n32 {
pub fn new(value: u32) -> Self {
n32(value.to_be())
}
pub fn get(&self) -> u32 {
u32::from_be(self.0)
}
pub fn set(&mut self, value: u32) {
self.0 = value.to_be();
}
}
#[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)
}
}
pub const TCP_FIN: u16 = 1;
pub const TCP_SYN: u16 = 1 << 1;
pub const TCP_RST: u16 = 1 << 2;
pub const TCP_PSH: u16 = 1 << 3;
pub const TCP_ACK: u16 = 1 << 4;
#[derive(Copy, Clone)]
#[repr(packed)]
pub struct TcpHeader {
pub src: n16,
pub dst: n16,
pub sequence: n32,
pub ack_num: n32,
pub flags: n16,
pub window_size: n16,
pub checksum: Checksum,
pub urgent_pointer: n16,
}
pub struct Tcp {
pub header: TcpHeader,
pub options: Vec<u8>,
pub data: Vec<u8>,
}
impl Tcp {
pub fn checksum(&mut self, src_addr: &Ipv4Addr, dst_addr: &Ipv4Addr) {
self.header.checksum.data = 0;
let proto = n16::new(0x06);
let segment_len = n16::new((mem::size_of::<TcpHeader>() + self.options.len() + self.data.len()) as u16);
self.header.checksum.data = Checksum::compile(unsafe {
Checksum::sum(src_addr.bytes.as_ptr() as usize, src_addr.bytes.len()) +
Checksum::sum(dst_addr.bytes.as_ptr() as usize, dst_addr.bytes.len()) +
Checksum::sum((&proto as *const n16) as usize, mem::size_of::<n16>()) +
Checksum::sum((&segment_len as *const n16) as usize, mem::size_of::<n16>()) +
Checksum::sum((&self.header as *const TcpHeader) as usize, mem::size_of::<TcpHeader>()) +
Checksum::sum(self.options.as_ptr() as usize, self.options.len()) +
Checksum::sum(self.data.as_ptr() as usize, self.data.len())
});
}
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() >= mem::size_of::<TcpHeader>() {
unsafe {
let header = *(bytes.as_ptr() as *const TcpHeader);
let header_len = ((header.flags.get() & 0xF000) >> 10) as usize;
return Some(Tcp {
header: header,
options: bytes[mem::size_of::<TcpHeader>()..header_len].to_vec(),
data: bytes[header_len..bytes.len()].to_vec(),
});
}
}
None
}
pub fn to_bytes(&self) -> Vec<u8> {
unsafe {
let header_ptr: *const TcpHeader = &self.header;
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
mem::size_of::<TcpHeader>()));
ret.extend_from_slice(&self.options);
ret.extend_from_slice(&self.data);
ret
}
}
}

View file

@ -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::TcpScheme;
pub mod common;
pub mod resource;
pub mod scheme;
mod resource;
mod scheme;
fn main() {
thread::spawn(move || {

View file

@ -2,14 +2,14 @@ use std::{cmp, mem};
use std::cell::UnsafeCell;
use std::sync::Arc;
use netutils::{n16, n32, Ipv4Addr, Checksum, Tcp, TcpHeader, TCP_SYN, TCP_PSH, TCP_FIN, TCP_ACK};
use resource_scheme::Resource;
use syscall;
use syscall::error::*;
use common::{n16, n32, Ipv4Addr, Checksum, IP_ADDR, Tcp, TcpHeader, TCP_SYN, TCP_PSH, TCP_FIN, TCP_ACK};
pub struct TcpStream {
pub ip: usize,
pub host_addr: Ipv4Addr,
pub peer_addr: Ipv4Addr,
pub peer_port: u16,
pub host_port: u16,
@ -74,7 +74,7 @@ impl TcpStream {
data: Vec::new()
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
//println!("Sending read ack: {} {} {:X}", tcp.header.sequence.get(), tcp.header.ack_num.get(), tcp.header.flags.get());
@ -117,7 +117,7 @@ impl TcpStream {
data: tcp_data,
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(size) => {
@ -169,7 +169,7 @@ impl TcpStream {
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(_) => {
@ -203,7 +203,7 @@ impl TcpStream {
data: Vec::new()
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
let _ = syscall::write(self.ip, &tcp.to_bytes());
@ -242,7 +242,7 @@ impl TcpStream {
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
match syscall::write(self.ip, &tcp.to_bytes()) {
Ok(_) => {
@ -291,7 +291,7 @@ impl Drop for TcpStream {
data: Vec::new(),
};
tcp.checksum(& unsafe { IP_ADDR }, &self.peer_addr);
tcp.checksum(&self.host_addr, &self.peer_addr);
let _ = syscall::write(self.ip, &tcp.to_bytes());
let _ = syscall::close(self.ip);

View file

@ -3,12 +3,12 @@ use std::rand;
use std::sync::Arc;
use std::{str, u16};
use netutils::{getcfg, Ipv4Addr, Tcp, TCP_SYN, TCP_ACK};
use resource_scheme::ResourceScheme;
use syscall;
use syscall::error::{Error, Result, ENOENT, EINVAL};
use syscall::flag::O_RDWR;
use common::{Ipv4Addr, Tcp, TCP_SYN, TCP_ACK};
use resource::{TcpResource, TcpStream};
/// A TCP scheme
@ -16,6 +16,8 @@ pub struct TcpScheme;
impl ResourceScheme<TcpResource> for TcpScheme {
fn open_resource(&self, url: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<Box<TcpResource>> {
let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
let mut parts = path.split('/');
let remote = parts.next().unwrap_or("");
@ -34,6 +36,7 @@ impl ResourceScheme<TcpResource> for TcpScheme {
Ok(ip) => {
let mut stream = TcpStream {
ip: ip,
host_addr: ip_addr,
peer_addr: peer_addr,
peer_port: peer_port,
host_port: host_port,
@ -67,6 +70,7 @@ impl ResourceScheme<TcpResource> for TcpScheme {
let mut stream = TcpStream {
ip: ip,
host_addr: ip_addr,
peer_addr: Ipv4Addr::from_str(peer_addr),
peer_port: segment.header.src.get(),
host_port: host_port,

View file

@ -3,5 +3,6 @@ name = "udpd"
version = "0.1.0"
[dependencies]
netutils = { path = "../../programs/netutils/" }
resource_scheme = { path = "../../crates/resource_scheme/" }
syscall = { path = "../../syscall/" }

View file

@ -1,167 +0,0 @@
use std::{mem, slice, u8, u16};
pub static mut IP_ADDR: Ipv4Addr = Ipv4Addr { bytes: [10, 0, 2, 15] };
#[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 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 UdpHeader {
pub src: n16,
pub dst: n16,
pub len: n16,
pub checksum: Checksum,
}
pub struct Udp {
pub header: UdpHeader,
pub data: Vec<u8>,
}
impl Udp {
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() >= mem::size_of::<UdpHeader>() {
unsafe {
Option::Some(Udp {
header: *(bytes.as_ptr() as *const UdpHeader),
data: bytes[mem::size_of::<UdpHeader>()..bytes.len()].to_vec(),
})
}
} else {
Option::None
}
}
pub fn to_bytes(&self) -> Vec<u8> {
unsafe {
let header_ptr: *const UdpHeader = &self.header;
let mut ret = Vec::from(slice::from_raw_parts(header_ptr as *const u8,
mem::size_of::<UdpHeader>()));
ret.extend_from_slice(&self.data);
ret
}
}
}

View file

@ -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::UdpScheme;
pub mod common;
pub mod resource;
pub mod scheme;
mod resource;
mod scheme;
fn main() {
thread::spawn(move || {

View file

@ -1,15 +1,15 @@
use std::{cmp, mem};
use netutils::{n16, Ipv4Addr, Checksum, Udp, UdpHeader};
use resource_scheme::Resource;
use syscall;
use syscall::error::*;
use common::{n16, Ipv4Addr, Checksum, IP_ADDR, Udp, UdpHeader};
/// UDP resource
pub struct UdpResource {
pub ip: usize,
pub data: Vec<u8>,
pub host_addr: Ipv4Addr,
pub peer_addr: Ipv4Addr,
pub peer_port: u16,
pub host_port: u16,
@ -22,6 +22,7 @@ impl Resource for UdpResource {
Ok(Box::new(UdpResource {
ip: ip,
data: self.data.clone(),
host_addr: self.host_addr,
peer_addr: self.peer_addr,
peer_port: self.peer_port,
host_port: self.host_port,
@ -92,7 +93,7 @@ impl Resource for UdpResource {
let proto = n16::new(0x11);
let datagram_len = n16::new((mem::size_of::<UdpHeader>() + udp.data.len()) as u16);
udp.header.checksum.data =
Checksum::compile(Checksum::sum((&IP_ADDR as *const Ipv4Addr) as usize,
Checksum::compile(Checksum::sum((&self.host_addr as *const Ipv4Addr) as usize,
mem::size_of::<Ipv4Addr>()) +
Checksum::sum((&self.peer_addr as *const Ipv4Addr) as usize,
mem::size_of::<Ipv4Addr>()) +

View file

@ -1,12 +1,12 @@
use std::rand;
use std::{str, u16};
use netutils::{getcfg, Ipv4Addr, Udp};
use resource_scheme::ResourceScheme;
use syscall;
use syscall::error::{Error, Result, ENOENT, EINVAL};
use syscall::flag::O_RDWR;
use common::{Ipv4Addr, Udp};
use resource::UdpResource;
/// UDP UdpScheme
@ -14,6 +14,8 @@ pub struct UdpScheme;
impl ResourceScheme<UdpResource> for UdpScheme {
fn open_resource(&self, url: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<Box<UdpResource>> {
let ip_addr = Ipv4Addr::from_str(&getcfg("ip").map_err(|err| err.into_sys())?);
let path = try!(str::from_utf8(url).or(Err(Error::new(EINVAL))));
let mut parts = path.split('/');
let remote = parts.next().unwrap_or("");
@ -36,6 +38,7 @@ impl ResourceScheme<UdpResource> for UdpScheme {
return Ok(Box::new(UdpResource {
ip: ip,
data: datagram.data,
host_addr: ip_addr,
peer_addr: Ipv4Addr::from_str(peer_addr),
peer_port: datagram.header.src.get(),
host_port: host_port,
@ -56,6 +59,7 @@ impl ResourceScheme<UdpResource> for UdpScheme {
return Ok(Box::new(UdpResource {
ip: ip,
data: Vec::new(),
host_addr: ip_addr,
peer_addr: Ipv4Addr::from_str(peer_addr),
peer_port: peer_port as u16,
host_port: host_port,