Skip to content

Commit

Permalink
Merge pull request bparli#37 from rcloran/icmpv6
Browse files Browse the repository at this point in the history
Implement ICMPv6 sequence and identifier
  • Loading branch information
bparli authored Sep 7, 2023
2 parents 431e2bb + e13abc6 commit 883621e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 55 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ description = " ICMP ping library for quickly sending and measuring batches of I
readme = "README.md"

[dependencies]
pnet = "0.28"
pnet_macros_support = "0.28"
pnet = "0.34"
pnet_macros_support = "0.34"
log = "0.4"
rand = "0.8"

[dev-dependencies]
pretty_env_logger = "0.4"
pretty_env_logger = "0.5"

[[example]]
name = "ping"
54 changes: 29 additions & 25 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ extern crate rand;
mod ping;

use ping::{send_pings, Ping, ReceivedPing};
use pnet::packet::icmp::echo_reply::EchoReplyPacket;
use pnet::packet::icmp::echo_reply::EchoReplyPacket as IcmpEchoReplyPacket;
use pnet::packet::icmpv6::echo_reply::EchoReplyPacket as Icmpv6EchoReplyPacket;
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::Packet;
use pnet::packet::{icmp, icmpv6};
Expand Down Expand Up @@ -227,9 +228,9 @@ impl Pinger {
let mut iter = icmp_packet_iter(&mut receiver);
loop {
match iter.next() {
Ok((packet, addr)) => match EchoReplyPacket::new(packet.packet()) {
Ok((packet, addr)) => match IcmpEchoReplyPacket::new(packet.packet()) {
Some(echo_reply) => {
if packet.get_icmp_type() == icmp::IcmpType::new(0) {
if packet.get_icmp_type() == icmp::IcmpTypes::EchoReply {
let start_time = timer.read().unwrap();
match thread_tx.send(ReceivedPing {
addr,
Expand Down Expand Up @@ -274,32 +275,35 @@ impl Pinger {
let mut iter = icmpv6_packet_iter(&mut receiver);
loop {
match iter.next() {
Ok((packet, addr)) => {
if packet.get_icmpv6_type() == icmpv6::Icmpv6Type::new(129) {
let start_time = timerv6.read().unwrap();
match thread_txv6.send(ReceivedPing {
addr,
identifier: 0,
sequence_number: 0,
rtt: Instant::now().duration_since(*start_time),
}) {
Ok(_) => {}
Err(e) => {
if !*stopv6.lock().unwrap() {
error!("Error sending ping result on channel: {}", e)
} else {
return;
Ok((packet, addr)) => match Icmpv6EchoReplyPacket::new(packet.packet()) {
Some(echo_reply) => {
if packet.get_icmpv6_type() == icmpv6::Icmpv6Types::EchoReply {
let start_time = timerv6.read().unwrap();
match thread_txv6.send(ReceivedPing {
addr,
identifier: echo_reply.get_identifier(),
sequence_number: echo_reply.get_sequence_number(),
rtt: Instant::now().duration_since(*start_time),
}) {
Ok(_) => {}
Err(e) => {
if !*stopv6.lock().unwrap() {
error!("Error sending ping result on channel: {}", e)
} else {
return;
}
}
}
} else {
debug!(
"ICMPv6 type other than reply (129) received from {:?}: {:?}",
addr,
packet.get_icmpv6_type()
);
}
} else {
debug!(
"ICMP type other than reply (129) received from {:?}: {:?}",
addr,
packet.get_icmpv6_type()
);
}
}
None => {}
},
Err(e) => {
error!("An error occurred while reading: {}", e);
}
Expand Down
41 changes: 14 additions & 27 deletions src/ping.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use pnet::packet::icmp::echo_request;
use pnet::packet::icmp::IcmpTypes;
use pnet::packet::icmpv6::{Icmpv6Types, MutableIcmpv6Packet};
use pnet::packet::Packet;
use pnet::packet::{icmp, icmpv6};
use pnet::transport::TransportSender;
use pnet::util;
use pnet_macros_support::types::*;
use rand::random;
use std::collections::BTreeMap;
use std::net::IpAddr;
Expand All @@ -29,13 +26,9 @@ pub struct ReceivedPing {

impl Ping {
pub fn new(addr: IpAddr) -> Ping {
let mut identifier = 0;
if addr.is_ipv4() {
identifier = random::<u16>();
}
Ping {
addr,
identifier,
identifier: random::<u16>(),
sequence_number: 0,
seen: false,
}
Expand Down Expand Up @@ -67,33 +60,35 @@ fn send_echo(
// Allocate enough space for a new packet
let mut vec: Vec<u8> = vec![0; size];

// Use echo_request so we can set the identifier and sequence number
let mut echo_packet = echo_request::MutableEchoRequestPacket::new(&mut vec[..]).unwrap();
let mut echo_packet = icmp::echo_request::MutableEchoRequestPacket::new(&mut vec[..]).unwrap();
echo_packet.set_sequence_number(ping.increment_sequence_number());
echo_packet.set_identifier(ping.get_identifier());
echo_packet.set_icmp_type(IcmpTypes::EchoRequest);
echo_packet.set_icmp_type(icmp::IcmpTypes::EchoRequest);

let csum = icmp_checksum(&echo_packet);
let csum = util::checksum(echo_packet.packet(), 1);
echo_packet.set_checksum(csum);

tx.send_to(echo_packet, ping.get_addr())
}

fn send_echov6(
tx: &mut TransportSender,
addr: IpAddr,
ping: &mut Ping,
size: usize,
) -> Result<usize, std::io::Error> {
// Allocate enough space for a new packet
let mut vec: Vec<u8> = vec![0; size];

let mut echo_packet = MutableIcmpv6Packet::new(&mut vec[..]).unwrap();
echo_packet.set_icmpv6_type(Icmpv6Types::EchoRequest);
let mut echo_packet =
icmpv6::echo_request::MutableEchoRequestPacket::new(&mut vec[..]).unwrap();
echo_packet.set_sequence_number(ping.increment_sequence_number());
echo_packet.set_identifier(ping.get_identifier());
echo_packet.set_icmpv6_type(icmpv6::Icmpv6Types::EchoRequest);

let csum = icmpv6_checksum(&echo_packet);
let csum = util::checksum(echo_packet.packet(), 1);
echo_packet.set_checksum(csum);

tx.send_to(echo_packet, addr)
tx.send_to(echo_packet, ping.get_addr())
}

pub fn send_pings(
Expand All @@ -112,7 +107,7 @@ pub fn send_pings(
match if addr.is_ipv4() {
send_echo(&mut tx.lock().unwrap(), ping, size)
} else if addr.is_ipv6() {
send_echov6(&mut txv6.lock().unwrap(), *addr, size)
send_echov6(&mut txv6.lock().unwrap(), ping, size)
} else {
Ok(0)
} {
Expand Down Expand Up @@ -194,14 +189,6 @@ pub fn send_pings(
}
}

fn icmp_checksum(packet: &echo_request::MutableEchoRequestPacket) -> u16be {
util::checksum(packet.packet(), 1)
}

fn icmpv6_checksum(packet: &MutableIcmpv6Packet) -> u16be {
util::checksum(packet.packet(), 1)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 883621e

Please sign in to comment.