Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VLAN Q-in-Q parsing support #9

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
os:
- linux
dist: bionic
dist: focal

language: rust
rust:
- stable

before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get -y install libpcap-dev tshark; fi
- sudo apt-get -y install libpcap-dev tshark
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Small, fast, and correct L2/L3/L4 packet parser.

The following protocol hierarchy can be parsed with this library:

* Ethernet (including vlan)
* Ethernet (including vlan/QinQ)
* ARP
* IPv4 (including options)
* TCP (including options)
Expand Down
16 changes: 8 additions & 8 deletions fuzz.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,26 @@ fi
DOCKER="docker"

${DOCKER} build -t pdu-fuzz - <<'EOF'
FROM ubuntu:bionic
ENV LANG=C.UTF-8 \
LC_ALL=C.UTF-8
FROM ubuntu:focal
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
VOLUME /usr/local/src/pdu
WORKDIR /usr/local/src/pdu
SHELL ["/bin/bash", "-eu", "-o", "pipefail", "-c"]
RUN \
export DEBIAN_FRONTEND=noninteractive; \
apt-get -q update; \
apt-get -q install -y curl build-essential linux-headers-generic pkg-config binutils-dev libunwind-dev libpcap-dev tshark; \
apt-get -q install -y curl build-essential linux-headers-generic pkg-config binutils-dev libunwind-dev libblocksruntime-dev liblzma-dev libpcap-dev tshark; \
apt-get -q clean autoclean;
RUN \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable; \
source $HOME/.cargo/env; \
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable;
RUN source $HOME/.cargo/env; \
cargo install honggfuzz;
ENTRYPOINT \
mkdir -p /tmp/honggfuzz/$FUZZ_TARGET; \
source $HOME/.cargo/env; \
cd ./fuzz; \
RUSTFLAGS="-C link-dead-code" HFUZZ_RUN_ARGS="-t 5 -T --output /tmp/honggfuzz/$FUZZ_TARGET" cargo hfuzz run $FUZZ_TARGET
export RUSTFLAGS="-C link-dead-code"; \
export HFUZZ_RUN_ARGS="-t 5 -T --output /tmp/honggfuzz/$FUZZ_TARGET"; \
cargo hfuzz run $FUZZ_TARGET
EOF

if [ -z "$1" ]; then
Expand Down
27 changes: 12 additions & 15 deletions fuzz/src/bin/arp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,26 +19,23 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match ArpPdu::new(&data) {
Ok(arp_pdu) => {
arp_pdu.hardware_type();
arp_pdu.protocol_type();
arp_pdu.hardware_length();
arp_pdu.protocol_length();
arp_pdu.opcode();
arp_pdu.sender_hardware_address();
arp_pdu.sender_protocol_address();
arp_pdu.target_hardware_address();
arp_pdu.target_protocol_address();
}
Err(_) => {}
if let Ok(arp_pdu) = ArpPdu::new(data) {
arp_pdu.hardware_type();
arp_pdu.protocol_type();
arp_pdu.hardware_length();
arp_pdu.protocol_length();
arp_pdu.opcode();
arp_pdu.sender_hardware_address();
arp_pdu.sender_protocol_address();
arp_pdu.target_hardware_address();
arp_pdu.target_protocol_address();
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
27 changes: 15 additions & 12 deletions fuzz/src/bin/ethernet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,24 +19,27 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match EthernetPdu::new(&data) {
Ok(ethernet_pdu) => {
ethernet_pdu.computed_ihl();
ethernet_pdu.destination_address();
ethernet_pdu.source_address();
ethernet_pdu.ethertype();
ethernet_pdu.vlan();
ethernet_pdu.vlan_pcp();
ethernet_pdu.vlan_dei();
if let Ok(ethernet_pdu) = EthernetPdu::new(data) {
ethernet_pdu.computed_ihl();
ethernet_pdu.destination_address();
ethernet_pdu.source_address();
ethernet_pdu.ethertype();
ethernet_pdu.computed_ethertype();
if let Some(vlan_tags) = ethernet_pdu.vlan_tags() {
for vlan_tag in vlan_tags {
vlan_tag.protocol_id;
vlan_tag.priority_codepoint;
vlan_tag.drop_eligible;
vlan_tag.id;
}
}
Err(_) => {}
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
23 changes: 10 additions & 13 deletions fuzz/src/bin/gre.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,24 +19,21 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match GrePdu::new(&data) {
Ok(gre_pdu) => {
gre_pdu.computed_ihl();
gre_pdu.version();
gre_pdu.ethertype();
gre_pdu.checksum();
gre_pdu.computed_checksum();
gre_pdu.key();
gre_pdu.sequence_number();
}
Err(_) => {}
if let Ok(gre_pdu) = GrePdu::new(data) {
gre_pdu.computed_ihl();
gre_pdu.version();
gre_pdu.ethertype();
gre_pdu.checksum();
gre_pdu.computed_checksum();
gre_pdu.key();
gre_pdu.sequence_number();
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
49 changes: 23 additions & 26 deletions fuzz/src/bin/icmp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,37 +19,34 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match IcmpPdu::new(&data) {
Ok(icmp_pdu) => {
icmp_pdu.message_type();
icmp_pdu.message_code();
icmp_pdu.checksum();
let ip = Ip::Ipv4(
Ipv4Pdu::new(&[
0x45u8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
])
.unwrap(),
);
icmp_pdu.computed_checksum(&ip);
let ip = Ip::Ipv6(
Ipv6Pdu::new(&[
0x60u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
])
.unwrap(),
);
icmp_pdu.computed_checksum(&ip);
}
Err(_) => {}
if let Ok(icmp_pdu) = IcmpPdu::new(data) {
icmp_pdu.message_type();
icmp_pdu.message_code();
icmp_pdu.checksum();
let ip = Ip::Ipv4(
Ipv4Pdu::new(&[
0x45u8, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
])
.unwrap(),
);
icmp_pdu.computed_checksum(&ip);
let ip = Ip::Ipv6(
Ipv6Pdu::new(&[
0x60u8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
])
.unwrap(),
);
icmp_pdu.computed_checksum(&ip);
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
49 changes: 23 additions & 26 deletions fuzz/src/bin/ipv4.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,40 +19,37 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match Ipv4Pdu::new(&data) {
Ok(ipv4_pdu) => {
ipv4_pdu.version();
ipv4_pdu.ihl();
ipv4_pdu.computed_ihl();
ipv4_pdu.dscp();
ipv4_pdu.ecn();
ipv4_pdu.total_length();
ipv4_pdu.identification();
ipv4_pdu.dont_fragment();
ipv4_pdu.more_fragments();
ipv4_pdu.fragment_offset();
ipv4_pdu.ttl();
ipv4_pdu.protocol();
ipv4_pdu.checksum();
ipv4_pdu.computed_checksum();
ipv4_pdu.source_address();
ipv4_pdu.destination_address();
for option in ipv4_pdu.options() {
match option {
Ipv4Option::Raw { .. } => {
continue;
}
if let Ok(ipv4_pdu) = Ipv4Pdu::new(data) {
ipv4_pdu.version();
ipv4_pdu.ihl();
ipv4_pdu.computed_ihl();
ipv4_pdu.dscp();
ipv4_pdu.ecn();
ipv4_pdu.total_length();
ipv4_pdu.identification();
ipv4_pdu.dont_fragment();
ipv4_pdu.more_fragments();
ipv4_pdu.fragment_offset();
ipv4_pdu.ttl();
ipv4_pdu.protocol();
ipv4_pdu.checksum();
ipv4_pdu.computed_checksum();
ipv4_pdu.source_address();
ipv4_pdu.destination_address();
for option in ipv4_pdu.options() {
match option {
Ipv4Option::Raw { .. } => {
continue;
}
}
}
Err(_) => {}
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
51 changes: 24 additions & 27 deletions fuzz/src/bin/ipv6.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright (c) 2019 Alex Forster <[email protected]>
Copyright (c) Alex Forster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,41 +19,38 @@
use pdu::*;

pub fn fuzz(data: &[u8]) {
match Ipv6Pdu::new(&data) {
Ok(ipv6_pdu) => {
ipv6_pdu.version();
ipv6_pdu.dscp();
ipv6_pdu.ecn();
ipv6_pdu.flow_label();
ipv6_pdu.payload_length();
ipv6_pdu.next_header();
ipv6_pdu.computed_ihl();
ipv6_pdu.computed_protocol();
ipv6_pdu.computed_identification();
ipv6_pdu.computed_more_fragments();
ipv6_pdu.computed_fragment_offset();
ipv6_pdu.hop_limit();
ipv6_pdu.source_address();
ipv6_pdu.destination_address();
for extension_header in ipv6_pdu.extension_headers() {
match extension_header {
Ipv6ExtensionHeader::Raw { .. } => {
continue;
}
Ipv6ExtensionHeader::Fragment { .. } => {
continue;
}
if let Ok(ipv6_pdu) = Ipv6Pdu::new(data) {
ipv6_pdu.version();
ipv6_pdu.dscp();
ipv6_pdu.ecn();
ipv6_pdu.flow_label();
ipv6_pdu.payload_length();
ipv6_pdu.next_header();
ipv6_pdu.computed_ihl();
ipv6_pdu.computed_protocol();
ipv6_pdu.computed_identification();
ipv6_pdu.computed_more_fragments();
ipv6_pdu.computed_fragment_offset();
ipv6_pdu.hop_limit();
ipv6_pdu.source_address();
ipv6_pdu.destination_address();
for extension_header in ipv6_pdu.extension_headers() {
match extension_header {
Ipv6ExtensionHeader::Raw { .. } => {
continue;
}
Ipv6ExtensionHeader::Fragment { .. } => {
continue;
}
}
}
Err(_) => {}
}
}

fn main() {
loop {
honggfuzz::fuzz!(|data: &[u8]| {
fuzz(&data);
fuzz(data);
});
}
}
Loading