Skip to content

Edition upgrade & dependency updates & code style fixes & integration tests #6

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
[package]
name = "packet-builder"
version = "0.7.0"
edition = "2021"
description = "High-level library for interacting with low-level network data."
homepage = "https://github.com/hughesac/packet_builder"
repository = "https://github.com/hughesac/packet_builder"
license = "MIT OR Apache-2.0"
authors = [
"Aaron Hughes <[email protected]>",
]
authors = ["Aaron Hughes <[email protected]>"]
readme = "README.md"
keywords = ["networking", "transport", "packet", "protocol", "packet-crafting"]
categories = ["network-programming"]


[dependencies]
derive-new = "0.5"
ipnetwork = "0.19.0"
pnet_datalink = "0.31.0"
pnet = "0.31.0"
ipnetwork = "0.20.0"
pnet_datalink = "0.34.0"
pnet = "0.34.0"
10 changes: 4 additions & 6 deletions examples/main.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
extern crate packet_builder;
extern crate pnet_datalink;
extern crate pnet;
extern crate pnet_datalink;

use packet_builder::payload::PayloadData;
use packet_builder::*;
use pnet_datalink::Channel::Ethernet;
use pnet_datalink::NetworkInterface;
use pnet::packet::icmp::IcmpTypes;
use pnet::packet::tcp::TcpFlags;
use pnet::packet::tcp::TcpOption;
use pnet::packet::Packet;
use pnet::util::MacAddr;
use pnet_datalink::Channel::Ethernet;
use pnet_datalink::NetworkInterface;
use std::env;

fn main() {
Expand All @@ -22,8 +21,7 @@ fn main() {
let interfaces = pnet_datalink::interfaces();
let interface = interfaces
.into_iter()
.filter(|iface: &NetworkInterface| iface.name == if_name)
.next()
.find(|iface: &NetworkInterface| iface.name == if_name)
.unwrap_or_else(|| panic!("No such network interface: {}", if_name));

let (mut sender, mut _receiver) = match pnet_datalink::channel(&interface, Default::default()) {
Expand Down
48 changes: 23 additions & 25 deletions src/arp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


#[macro_export]
macro_rules! arp {
({$($func:ident => $value:expr), *}, $buf:expr) => {{
Expand All @@ -12,9 +10,9 @@ macro_rules! arp {
pkt.set_sender_proto_addr("127.0.0.1".parse().unwrap());
pkt.set_target_proto_addr("192.168.1.1".parse().unwrap());
pkt.set_operation(pnet::packet::arp::ArpOperations::Request);
pkt.set_hardware_type(pnet::packet::arp::ArpHardwareTypes::Ethernet);
pkt.set_protocol_type(pnet::packet::ethernet::EtherTypes::Ipv4);
pkt.set_sender_hw_addr(pnet::util::MacAddr(1,2,3,4,5,6));
pkt.set_hardware_type(pnet::packet::arp::ArpHardwareTypes::Ethernet);
pkt.set_protocol_type(pnet::packet::ethernet::EtherTypes::Ipv4);
pkt.set_sender_hw_addr(pnet::util::MacAddr(1,2,3,4,5,6));
$(
pkt.$func($value);
)*
Expand All @@ -24,26 +22,26 @@ macro_rules! arp {

#[cfg(test)]
mod tests {
use pnet::packet::Packet;
use ::ipv4addr;
use pnet::packet::Packet;

#[test]
fn macro_arp_basic() {
let mut buf = [0; 28];
let (pkt, proto) = arp!({set_target_proto_addr => ipv4addr!("192.168.1.1"), set_sender_proto_addr => ipv4addr!("192.168.1.245")}, buf);
assert_eq!(proto, pnet::packet::ethernet::EtherTypes::Arp );
use crate::ipv4addr;

let buf_expected = vec![0; 28];
let mut pkt_expected = pnet::packet::arp::MutableArpPacket::owned(buf_expected).unwrap();
pkt_expected.set_hw_addr_len(6);
pkt_expected.set_proto_addr_len(4);
pkt_expected.set_sender_proto_addr("192.168.1.245".parse().unwrap());
pkt_expected.set_target_proto_addr("192.168.1.1".parse().unwrap());
pkt_expected.set_operation(pnet::packet::arp::ArpOperations::Request);
pkt_expected.set_hardware_type(pnet::packet::arp::ArpHardwareTypes::Ethernet);
pkt_expected.set_protocol_type(pnet::packet::ethernet::EtherTypes::Ipv4);
pkt_expected.set_sender_hw_addr(pnet::util::MacAddr(1,2,3,4,5,6));
assert_eq!(pkt_expected.packet(), pkt.packet());
}
}
#[test]
fn macro_arp_basic() {
let mut buf = [0; 28];
let (pkt, proto) = arp!({set_target_proto_addr => ipv4addr!("192.168.1.1"), set_sender_proto_addr => ipv4addr!("192.168.1.245")}, buf);
assert_eq!(proto, pnet::packet::ethernet::EtherTypes::Arp);

let buf_expected = vec![0; 28];
let mut pkt_expected = pnet::packet::arp::MutableArpPacket::owned(buf_expected).unwrap();
pkt_expected.set_hw_addr_len(6);
pkt_expected.set_proto_addr_len(4);
pkt_expected.set_sender_proto_addr("192.168.1.245".parse().unwrap());
pkt_expected.set_target_proto_addr("192.168.1.1".parse().unwrap());
pkt_expected.set_operation(pnet::packet::arp::ArpOperations::Request);
pkt_expected.set_hardware_type(pnet::packet::arp::ArpHardwareTypes::Ethernet);
pkt_expected.set_protocol_type(pnet::packet::ethernet::EtherTypes::Ipv4);
pkt_expected.set_sender_hw_addr(pnet::util::MacAddr(1, 2, 3, 4, 5, 6));
assert_eq!(pkt_expected.packet(), pkt.packet());
}
}
143 changes: 97 additions & 46 deletions src/icmp.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,80 @@
use pnet::packet::util::checksum as generic_checksum;
use pnet::packet::Packet;
use std::net::Ipv4Addr;
use L4Checksum;

macro_rules! icmp_pkt_macro_generator {
($($name:ident => $icmp_type:ty), *) => {
$(
#[macro_export]
macro_rules! $name {
($args:tt, $payload_pkt:expr, $proto:expr, $buf:expr) => {{
icmp!($args, $payload_pkt, $icmp_type, $buf)
}};
($args:tt, $buf:expr) => {{
icmp!($args, $icmp_type, $buf)
}};
}
)*
};
use pnet::packet::{util::checksum as generic_checksum, Packet};

use crate::L4Checksum;

#[macro_export]
macro_rules! icmp_echo_req {
($args:tt, $payload_pkt:expr, $proto:expr, $buf:expr) => {{
$crate::icmp!(
$args,
$payload_pkt,
pnet::packet::icmp::echo_request::MutableEchoRequestPacket,
$buf
)
}};
($args:tt, $buf:expr) => {{
$crate::icmp!(
$args,
pnet::packet::icmp::echo_request::MutableEchoRequestPacket,
$buf
)
}};
}
#[macro_export]
macro_rules! icmp_echo_reply {
($args:tt, $payload_pkt:expr, $proto:expr, $buf:expr) => {{
$crate::icmp!(
$args,
$payload_pkt,
pnet::packet::icmp::echo_reply::MutableEchoReplyPacket,
$buf
)
}};
($args:tt, $buf:expr) => {{
$crate::icmp!(
$args,
pnet::packet::icmp::echo_reply::MutableEchoReplyPacket,
$buf
)
}};
}
#[macro_export]
macro_rules! icmp_dest_unreach {
($args:tt, $payload_pkt:expr, $proto:expr, $buf:expr) => {{
$crate::icmp!(
$args,
$payload_pkt,
pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket,
$buf
)
}};
($args:tt, $buf:expr) => {{
$crate::icmp!(
$args,
pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket,
$buf
)
}};
}
#[macro_export]
macro_rules! icmp_time_exceed {
($args:tt, $payload_pkt:expr, $proto:expr, $buf:expr) => {{
$crate::icmp!(
$args,
$payload_pkt,
pnet::packet::icmp::time_exceeded::MutableTimeExceededPacket,
$buf
)
}};
($args:tt, $buf:expr) => {{
$crate::icmp!(
$args,
pnet::packet::icmp::time_exceeded::MutableTimeExceededPacket,
$buf
)
}};
}

macro_rules! icmp_checksum_func_gen {
Expand All @@ -25,22 +83,19 @@ macro_rules! icmp_checksum_func_gen {
impl <'p>L4Checksum for $icmp_type {
fn checksum_ipv4(&mut self, _source: &Ipv4Addr, _destination: &Ipv4Addr) {
// ICMP checksum is the same as IP
self.set_checksum(generic_checksum(&self.packet(), 1));
self.set_checksum(generic_checksum(&self.packet(), 1));
}
}
)*
};
}

icmp_checksum_func_gen!(pnet::packet::icmp::echo_reply::MutableEchoReplyPacket<'p>,
pnet::packet::icmp::echo_request::MutableEchoRequestPacket<'p>,
pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket<'p>,
pnet::packet::icmp::time_exceeded::MutableTimeExceededPacket<'p>);

icmp_pkt_macro_generator!(icmp_echo_req => pnet::packet::icmp::echo_request::MutableEchoRequestPacket,
icmp_echo_reply => pnet::packet::icmp::echo_reply::MutableEchoReplyPacket,
icmp_dest_unreach => pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket,
icmp_time_exceed => pnet::packet::icmp::time_exceeded::MutableTimeExceededPacket);
icmp_checksum_func_gen!(
pnet::packet::icmp::echo_reply::MutableEchoReplyPacket<'p>,
pnet::packet::icmp::echo_request::MutableEchoRequestPacket<'p>,
pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket<'p>,
pnet::packet::icmp::time_exceeded::MutableTimeExceededPacket<'p>
);

#[macro_export]
macro_rules! icmp {
Expand All @@ -58,35 +113,31 @@ macro_rules! icmp {
let total_len = <$icmp_type>::minimum_packet_size() + $payload_pkt.packet().len();
let buf_len = $buf.len();
let mut pkt = <$icmp_type>::new(&mut $buf[buf_len - total_len..]).unwrap();
pkt.set_icmp_type(IcmpTypes::EchoRequest);
pkt.set_icmp_type(pnet::packet::icmp::IcmpTypes::EchoRequest);
$(
pkt.$func($value);
)*
(pkt, pnet::packet::ip::IpNextHeaderProtocols::Icmp)
}};
}


#[cfg(test)]
mod tests {
use pnet::packet::Packet;
use ::payload;
use payload::PayloadData;
use pnet::packet::icmp::{IcmpTypes};
use icmp;
use pnet::packet::{icmp::IcmpTypes, Packet};

#[test]
fn macro_icmp_basic() {
let mut buf = [0; 13];
let (pkt, proto) = icmp_dest_unreach!({set_icmp_type => IcmpTypes::DestinationUnreachable},
use crate::payload;

#[test]
fn macro_icmp_basic() {
let mut buf = [0; 13];
let (pkt, proto) = icmp_dest_unreach!({set_icmp_type => IcmpTypes::DestinationUnreachable},
payload!({"hello".to_string().into_bytes()}, buf).0, None, buf);
assert_eq!(proto, pnet::packet::ip::IpNextHeaderProtocols::Icmp);
assert_eq!(proto, pnet::packet::ip::IpNextHeaderProtocols::Icmp);

let buf_expected = vec![0; 13];
let mut pkt_expected = pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket::owned(buf_expected).unwrap();
pkt_expected.set_icmp_type(IcmpTypes::DestinationUnreachable);
pkt_expected.set_payload(&"hello".to_string().into_bytes());
assert_eq!(pkt_expected.packet(), pkt.packet());
}
let buf_expected = vec![0; 13];
let mut pkt_expected = pnet::packet::icmp::destination_unreachable::MutableDestinationUnreachablePacket::owned(buf_expected).unwrap();
pkt_expected.set_icmp_type(IcmpTypes::DestinationUnreachable);
pkt_expected.set_payload(&"hello".to_string().into_bytes());
assert_eq!(pkt_expected.packet(), pkt.packet());
}
}

Loading