Skip to content

Commit

Permalink
Stop slicing & decoding when packets when they are fragmented
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianSchmid committed Nov 28, 2021
1 parent 3121999 commit 2af0a70
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 41 deletions.
31 changes: 20 additions & 11 deletions src/packet_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,33 +75,42 @@ impl<'a> PacketHeaders<'a> {
match ether_type {
IPV4 => {
let (ip, ip_rest) = Ipv4Header::from_slice(rest)?;
let fragmented = ip.is_fragmenting_payload();
let (ip_ext, ip_protocol, ip_ext_rest) = Ipv4Extensions::from_slice(ip.protocol, ip_rest)?;

//set the ip result & rest
rest = ip_ext_rest;
result.ip = Some(IpHeader::Version4(ip, ip_ext));

//parse the transport layer
let (transport, transport_rest) = read_transport(ip_protocol, rest)?;
// only try to decode the transport layer if the payload
// is not fragmented
if false == fragmented {
//parse the transport layer
let (transport, transport_rest) = read_transport(ip_protocol, rest)?;

//assign to the output
rest = transport_rest;
result.transport = transport;

//assign to the output
rest = transport_rest;
result.transport = transport;
}
},
IPV6 => {
let (ip, ip_rest) = Ipv6Header::from_slice(rest)?;
let (ip_ext, next_header, ip_ext_rest) = Ipv6Extensions::from_slice(ip.next_header, ip_rest)?;
let fragmented = ip_ext.is_fragmenting_payload();

//set the ip result & rest
rest = ip_ext_rest;
result.ip = Some(IpHeader::Version6(ip, ip_ext));

//parse the transport layer
let (transport, transport_rest) = read_transport(next_header, rest)?;

rest = transport_rest;
result.transport = transport;
// only try to decode the transport layer if the payload
// is not fragmented
if false == fragmented {
//parse the transport layer
let (transport, transport_rest) = read_transport(next_header, rest)?;

rest = transport_rest;
result.transport = transport;
}

},
_ => {}
Expand Down
45 changes: 29 additions & 16 deletions src/packet_slicing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ impl<'a> CursorSlice<'a> {
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let fragmented = ip_header.is_fragmenting_payload();

// move the slice
self.move_by_slice(ip_header.slice());

Expand All @@ -271,17 +273,21 @@ impl<'a> CursorSlice<'a> {
err.add_slice_offset(self.offset)
)?;

// set the new data
// set the new data
self.move_to_slice(rest);
self.result.ip = Some(Ipv4(ip_header, ip_ext));

match protocol {
ip_number::UDP => self.slice_udp(),
ip_number::TCP => self.slice_tcp(),
value => {
use TransportSlice::*;
self.result.transport = Some(Unknown(value));
self.slice_payload()
if fragmented {
self.slice_payload()
} else {
match protocol {
ip_number::UDP => self.slice_udp(),
ip_number::TCP => self.slice_tcp(),
value => {
use TransportSlice::*;
self.result.transport = Some(Unknown(value));
self.slice_payload()
}
}
}
}
Expand All @@ -302,19 +308,26 @@ impl<'a> CursorSlice<'a> {
.map_err(|err|
err.add_slice_offset(self.offset)
)?;
let fragmented = ip_ext.is_fragmenting_payload();

// set the new data
self.move_to_slice(rest);
self.result.ip = Some(Ipv6(ip, ip_ext));

//parse the data bellow
match next_header {
ip_number::UDP => self.slice_udp(),
ip_number::TCP => self.slice_tcp(),
value => {
use TransportSlice::*;
self.result.transport = Some(Unknown(value));
self.slice_payload()
// only try to decode the transport layer if the payload
// is not fragmented
if fragmented {
self.slice_payload()
} else {
//parse the data bellow
match next_header {
ip_number::UDP => self.slice_udp(),
ip_number::TCP => self.slice_tcp(),
value => {
use TransportSlice::*;
self.result.transport = Some(Unknown(value));
self.slice_payload()
}
}
}
}
Expand Down
77 changes: 63 additions & 14 deletions tests/packet_compositions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,23 +340,72 @@ impl ComponentTest {
}

fn run_ipv4(&self, ip: &Ipv4Header, ip_exts: &Ipv4Extensions, udp: &UdpHeader, tcp: &TcpHeader) {
let mut test = self.clone();
test.ip = Some({
let mut header = IpHeader::Version4(ip.clone(), ip_exts.clone());
header.set_next_headers(ip.protocol);
header
});
test.run_transport(udp, tcp);

// fragmenting
{
let mut test = self.clone();
test.ip = Some({
let mut frag = ip.clone();
if false == frag.is_fragmenting_payload() {
frag.more_fragments = true;
}
let mut header = IpHeader::Version4(frag, ip_exts.clone());
header.set_next_headers(ip.protocol);
header
});

// run without transport header
test.run();
}

// non fragmenting
{
let mut test = self.clone();
test.ip = Some({
let mut non_frag = ip.clone();
non_frag.more_fragments = false;
non_frag.fragments_offset = 0;
let mut header = IpHeader::Version4(non_frag, ip_exts.clone());
header.set_next_headers(ip.protocol);
header
});
test.run_transport(udp, tcp);
}
}

fn run_ipv6(&self, ip: &Ipv6Header, ip_exts: &Ipv6Extensions, udp: &UdpHeader, tcp: &TcpHeader) {
let mut test = self.clone();
test.ip = Some({
let mut header = IpHeader::Version6(ip.clone(), ip_exts.clone());
header.set_next_headers(ip.next_header);
header
});
test.run_transport(udp, tcp);

// fragmenting
{
let mut test = self.clone();
test.ip = Some({
let mut frag = ip_exts.clone();
if let Some(frag) = frag.fragment.as_mut() {
if false == frag.is_fragmenting_payload() {
frag.more_fragments = true;
}
} else {
frag.fragment = Some(Ipv6FragmentHeader::new(ip_number::UDP, 0, true, 0));
}
let mut header = IpHeader::Version6(ip.clone(), frag);
header.set_next_headers(ip.next_header);
header
});
test.run();
}

// non fragmenting
{
let mut test = self.clone();
test.ip = Some({
let mut non_frag = ip_exts.clone();
non_frag.fragment = None;
let mut header = IpHeader::Version6(ip.clone(), non_frag);
header.set_next_headers(ip.next_header);
header
});
test.run_transport(udp, tcp);
}
}

fn run_transport(&self, udp: &UdpHeader, tcp: &TcpHeader) {
Expand Down

0 comments on commit 2af0a70

Please sign in to comment.