Skip to content

Commit

Permalink
Merge pull request #3
Browse files Browse the repository at this point in the history
Rudimentary TCP support
  • Loading branch information
phil-opp authored Aug 30, 2017
2 parents bfa81ea + 422ea4d commit ccd3238
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ version = "0.1.0"
license = "MIT/Apache-2.0"

[dependencies]
bit_field = "0.7.0"
bitflags-associated-constants = "0.6.0"
byteorder = { version = "1.0.0", default-features = false }

[features]
Expand Down
47 changes: 46 additions & 1 deletion src/ipv4.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use {TxPacket, WriteOut, ip_checksum};
use udp::UdpPacket;
use tcp::TcpPacket;
use icmp::IcmpPacket;
use core::convert::TryInto;
use core::fmt;
Expand Down Expand Up @@ -87,6 +88,19 @@ impl<T> Ipv4Packet<UdpPacket<T>> {
}
}

impl<'a, T> Ipv4Packet<&'a TcpPacket<T>> {
pub fn new_tcp(src_addr: Ipv4Address, dst_addr: Ipv4Address, tcp: &'a TcpPacket<T>) -> Self {
Ipv4Packet {
header: Ipv4Header {
src_addr: src_addr,
dst_addr: dst_addr,
protocol: IpProtocol::Tcp,
},
payload: tcp,
}
}
}

impl<T> Ipv4Packet<IcmpPacket<T>> {
pub fn new_icmp(src_addr: Ipv4Address, dst_addr: Ipv4Address, icmp: IcmpPacket<T>) -> Self {
Ipv4Packet {
Expand Down Expand Up @@ -169,8 +183,32 @@ impl<T: WriteOut> WriteOut for Ipv4Packet<UdpPacket<T>> {
}
}

impl<'a, T: WriteOut> WriteOut for Ipv4Packet<&'a TcpPacket<T>> {
fn write_out<P: TxPacket>(&self, packet: &mut P) -> Result<(), ()> {
self.write_out_impl(packet)?;

let tcp_start_index = packet.len();
self.payload.write_out(packet)?;

// calculate tcp checksum
let pseudo_header_checksum = !ip_checksum::pseudo_header(&self.header.src_addr,
&self.header.dst_addr,
self.header.protocol,
self.payload.len());

let tcp_checksum_idx = tcp_start_index + 16;
packet.update_u16(tcp_checksum_idx, |checksum| {
let checksums = [checksum, pseudo_header_checksum];
ip_checksum::combine(&checksums)
});

Ok(())
}
}

use parse::{Parse, ParseError};
use udp::UdpKind;
use tcp::TcpKind;

impl<'a> Parse<'a> for Ipv4Packet<&'a [u8]> {
fn parse(data: &'a [u8]) -> Result<Self, ParseError> {
Expand All @@ -191,6 +229,7 @@ impl<'a> Parse<'a> for Ipv4Packet<&'a [u8]> {
#[derive(Debug)]
pub enum Ipv4Kind<'a> {
Udp(UdpPacket<UdpKind<'a>>),
Tcp(TcpPacket<TcpKind<'a>>),
Icmp(IcmpPacket<&'a [u8]>),
Unknown(u8, &'a [u8]),
}
Expand All @@ -206,6 +245,13 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
payload: Ipv4Kind::Udp(udp),
})
}
IpProtocol::Tcp => {
let tcp = TcpPacket::parse(ip.payload)?;
Ok(Ipv4Packet {
header: ip.header,
payload: Ipv4Kind::Tcp(tcp),
})
}
IpProtocol::Icmp => {
let icmp = IcmpPacket::parse(ip.payload)?;
Ok(Ipv4Packet {
Expand All @@ -219,7 +265,6 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
payload: Ipv4Kind::Unknown(number, ip.payload),
})
}
_ => return Err(ParseError::Unimplemented("unimplemented ip protocol")),
}
}
}
Expand Down
26 changes: 11 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![feature(try_from)]
#![feature(specialization)]
#![feature(const_fn)]
#![feature(conservative_impl_trait)]

#![cfg_attr(not(test), no_std)]
#![cfg_attr(any(test, feature = "alloc"), feature(alloc))]
Expand All @@ -9,6 +10,7 @@
extern crate alloc;

extern crate byteorder;
extern crate bit_field;

#[cfg(test)]
mod core {
Expand All @@ -20,13 +22,17 @@ pub use parse::{parse, ParseError};
pub use heap_tx_packet::HeapTxPacket;

use core::ops::{Index, IndexMut, Range};
use alloc::borrow::Cow;
use core::borrow::Borrow;
use byteorder::{ByteOrder, NetworkEndian};

#[macro_use]
extern crate bitflags_associated_constants;

pub mod ethernet;
pub mod arp;
pub mod ipv4;
pub mod udp;
pub mod tcp;
pub mod dhcp;
pub mod icmp;
mod ip_checksum;
Expand Down Expand Up @@ -85,23 +91,13 @@ pub trait WriteOut {
fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()>;
}

impl<'a> WriteOut for &'a [u8] {
fn len(&self) -> usize {
<[u8]>::len(self)
}

fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()> {
packet.push_bytes(self).map(|_| ())
}
}

impl<'a> WriteOut for Cow<'a, [u8]> {
impl<T> WriteOut for T where T: Borrow<[u8]> {
fn len(&self) -> usize {
(**self).len()
<[u8]>::len(self.borrow())
}

fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()> {
packet.push_bytes(self).map(|_| ())
fn write_out<P: TxPacket>(&self, packet: &mut P) -> Result<(), ()> {
packet.push_bytes(self.borrow()).map(|_| ())
}
}

Expand Down
Loading

0 comments on commit ccd3238

Please sign in to comment.