Skip to content

Commit ccd3238

Browse files
authored
Merge pull request #3
Rudimentary TCP support
2 parents bfa81ea + 422ea4d commit ccd3238

File tree

4 files changed

+333
-16
lines changed

4 files changed

+333
-16
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ version = "0.1.0"
55
license = "MIT/Apache-2.0"
66

77
[dependencies]
8+
bit_field = "0.7.0"
9+
bitflags-associated-constants = "0.6.0"
810
byteorder = { version = "1.0.0", default-features = false }
911

1012
[features]

src/ipv4.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use {TxPacket, WriteOut, ip_checksum};
22
use udp::UdpPacket;
3+
use tcp::TcpPacket;
34
use icmp::IcmpPacket;
45
use core::convert::TryInto;
56
use core::fmt;
@@ -87,6 +88,19 @@ impl<T> Ipv4Packet<UdpPacket<T>> {
8788
}
8889
}
8990

91+
impl<'a, T> Ipv4Packet<&'a TcpPacket<T>> {
92+
pub fn new_tcp(src_addr: Ipv4Address, dst_addr: Ipv4Address, tcp: &'a TcpPacket<T>) -> Self {
93+
Ipv4Packet {
94+
header: Ipv4Header {
95+
src_addr: src_addr,
96+
dst_addr: dst_addr,
97+
protocol: IpProtocol::Tcp,
98+
},
99+
payload: tcp,
100+
}
101+
}
102+
}
103+
90104
impl<T> Ipv4Packet<IcmpPacket<T>> {
91105
pub fn new_icmp(src_addr: Ipv4Address, dst_addr: Ipv4Address, icmp: IcmpPacket<T>) -> Self {
92106
Ipv4Packet {
@@ -169,8 +183,32 @@ impl<T: WriteOut> WriteOut for Ipv4Packet<UdpPacket<T>> {
169183
}
170184
}
171185

186+
impl<'a, T: WriteOut> WriteOut for Ipv4Packet<&'a TcpPacket<T>> {
187+
fn write_out<P: TxPacket>(&self, packet: &mut P) -> Result<(), ()> {
188+
self.write_out_impl(packet)?;
189+
190+
let tcp_start_index = packet.len();
191+
self.payload.write_out(packet)?;
192+
193+
// calculate tcp checksum
194+
let pseudo_header_checksum = !ip_checksum::pseudo_header(&self.header.src_addr,
195+
&self.header.dst_addr,
196+
self.header.protocol,
197+
self.payload.len());
198+
199+
let tcp_checksum_idx = tcp_start_index + 16;
200+
packet.update_u16(tcp_checksum_idx, |checksum| {
201+
let checksums = [checksum, pseudo_header_checksum];
202+
ip_checksum::combine(&checksums)
203+
});
204+
205+
Ok(())
206+
}
207+
}
208+
172209
use parse::{Parse, ParseError};
173210
use udp::UdpKind;
211+
use tcp::TcpKind;
174212

175213
impl<'a> Parse<'a> for Ipv4Packet<&'a [u8]> {
176214
fn parse(data: &'a [u8]) -> Result<Self, ParseError> {
@@ -191,6 +229,7 @@ impl<'a> Parse<'a> for Ipv4Packet<&'a [u8]> {
191229
#[derive(Debug)]
192230
pub enum Ipv4Kind<'a> {
193231
Udp(UdpPacket<UdpKind<'a>>),
232+
Tcp(TcpPacket<TcpKind<'a>>),
194233
Icmp(IcmpPacket<&'a [u8]>),
195234
Unknown(u8, &'a [u8]),
196235
}
@@ -206,6 +245,13 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
206245
payload: Ipv4Kind::Udp(udp),
207246
})
208247
}
248+
IpProtocol::Tcp => {
249+
let tcp = TcpPacket::parse(ip.payload)?;
250+
Ok(Ipv4Packet {
251+
header: ip.header,
252+
payload: Ipv4Kind::Tcp(tcp),
253+
})
254+
}
209255
IpProtocol::Icmp => {
210256
let icmp = IcmpPacket::parse(ip.payload)?;
211257
Ok(Ipv4Packet {
@@ -219,7 +265,6 @@ impl<'a> Parse<'a> for Ipv4Packet<Ipv4Kind<'a>> {
219265
payload: Ipv4Kind::Unknown(number, ip.payload),
220266
})
221267
}
222-
_ => return Err(ParseError::Unimplemented("unimplemented ip protocol")),
223268
}
224269
}
225270
}

src/lib.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(try_from)]
22
#![feature(specialization)]
33
#![feature(const_fn)]
4+
#![feature(conservative_impl_trait)]
45

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

1112
extern crate byteorder;
13+
extern crate bit_field;
1214

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

2224
use core::ops::{Index, IndexMut, Range};
23-
use alloc::borrow::Cow;
25+
use core::borrow::Borrow;
2426
use byteorder::{ByteOrder, NetworkEndian};
2527

28+
#[macro_use]
29+
extern crate bitflags_associated_constants;
30+
2631
pub mod ethernet;
2732
pub mod arp;
2833
pub mod ipv4;
2934
pub mod udp;
35+
pub mod tcp;
3036
pub mod dhcp;
3137
pub mod icmp;
3238
mod ip_checksum;
@@ -85,23 +91,13 @@ pub trait WriteOut {
8591
fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()>;
8692
}
8793

88-
impl<'a> WriteOut for &'a [u8] {
89-
fn len(&self) -> usize {
90-
<[u8]>::len(self)
91-
}
92-
93-
fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()> {
94-
packet.push_bytes(self).map(|_| ())
95-
}
96-
}
97-
98-
impl<'a> WriteOut for Cow<'a, [u8]> {
94+
impl<T> WriteOut for T where T: Borrow<[u8]> {
9995
fn len(&self) -> usize {
100-
(**self).len()
96+
<[u8]>::len(self.borrow())
10197
}
10298

103-
fn write_out<T: TxPacket>(&self, packet: &mut T) -> Result<(), ()> {
104-
packet.push_bytes(self).map(|_| ())
99+
fn write_out<P: TxPacket>(&self, packet: &mut P) -> Result<(), ()> {
100+
packet.push_bytes(self.borrow()).map(|_| ())
105101
}
106102
}
107103

0 commit comments

Comments
 (0)